2222"""
2323import sublime
2424import sublime_plugin
25- import re
26- import subprocess
2725import os .path
28- import time
29- import os
30- import Queue
31- import threading
3226try :
33- from parsehelp import parsehelp
27+ from sublimecompletioncommon import completioncommon
3428except :
3529 def hack (func ):
3630 # If there's a sublime.error_message before a window is open
@@ -55,277 +49,43 @@ def showError():
5549 for more details.""" )
5650 hack (showError )
5751
58- scriptdir = os .path .dirname (os .path .abspath (__file__ ))
5952
53+ class SublimeJavaDotComplete (completioncommon .CompletionCommonDotComplete ):
54+ pass
6055
61- def get_settings ():
62- return sublime .load_settings ("SublimeJava.sublime-settings" )
63-
64-
65- def get_setting (key , default = None ):
66- try :
67- s = sublime .active_window ().active_view ().settings ()
68- if s .has (key ):
69- return s .get (key )
70- except :
71- pass
72- return get_settings ().get (key , default )
73-
74-
75- java_proc = None
76- java_cmd = None
77- data_queue = Queue .Queue ()
78- javaseparator = None # just so that get_cmd references it. It's set "for real" later
79-
80-
81- def get_cmd ():
82- classpath = "."
83- if javaseparator != None :
84- classpath = get_setting ("sublimejava_classpath" , ["." ])
85- classpath .append ("." )
86- classpath = javaseparator .join (classpath )
87- return "java -classpath %s SublimeJava" % classpath
88-
89-
90- def java_thread ():
91- global java_cmd
92- try :
93- while True :
94- if java_proc .poll () != None :
95- break
96- read = java_proc .stdout .readline ().strip ()
97- #print "read: %s" % read
98- if read :
99- data_queue .put (read )
100- finally :
101- #print "java_proc: %d" % (java_proc.poll())
102- data_queue .put (";;--;;" )
103- data_queue .put (";;--;;exit;;--;;" )
104- java_cmd = None
105- print "no longer running"
106-
107-
108- def run_java (cmd , stdin = None ):
109- global java_proc
110- global java_cmd
111- realcmd = get_cmd ()
112- if not java_proc or realcmd != java_cmd :
113- if java_proc :
114- java_proc .stdin .write ("-quit\n " )
115- while data_queue .get () != ";;--;;exit;;--;;" :
116- continue
117-
118- java_cmd = realcmd
119- java_proc = subprocess .Popen (
120- realcmd ,
121- cwd = scriptdir ,
122- shell = True ,
123- stdout = subprocess .PIPE ,
124- stdin = subprocess .PIPE
125- )
126- t = threading .Thread (target = java_thread )
127- t .start ()
128- #print "wrote: %s" % cmd
129- java_proc .stdin .write (cmd + "\n " )
130- if stdin :
131- #print "wrote: %s" % stdin
132- java_proc .stdin .write (stdin + "\n " )
133- stdout = ""
134- while True :
135- try :
136- read = data_queue .get (timeout = 5.0 )
137- if read == ";;--;;" or read == None :
138- break
139- stdout += read + "\n "
140- except :
141- break
142- return stdout
143-
144- javaseparator = run_java ("-separator" ).strip ()
145-
146- language_regex = re .compile ("(?<=source\.)[\w+#]+" )
147- member_regex = re .compile ("(([a-zA-Z_]+[0-9_]*)|([\)\]])+)(\.)$" )
148-
149-
150- def get_language (view ):
151- caret = view .sel ()[0 ].a
152- scope = view .scope_name (caret ).strip ()
153- language = language_regex .search (scope )
154- if language == None :
155- if scope .endswith ("jsp" ):
156- return "jsp"
157- return None
158- return language .group (0 )
159-
160-
161- def is_supported_language (view ):
162- if view .is_scratch () or not get_setting ("sublimejava_enabled" , True ):
163- return False
164- language = get_language (view )
165- return language == "java" or language == "jsp"
166-
167-
168- class SublimeJavaDotComplete (sublime_plugin .TextCommand ):
169- def run (self , edit ):
170- for region in self .view .sel ():
171- self .view .insert (edit , region .end (), "." )
172- caret = self .view .sel ()[0 ].begin ()
173- line = self .view .substr (sublime .Region (self .view .word (caret - 1 ).a , caret ))
174- if member_regex .search (line ) != None :
175- sublime .set_timeout (self .delayed_complete , 1 )
176-
177- def delayed_complete (self ):
178- self .view .run_command ("auto_complete" )
179-
180-
181- class SublimeJava (sublime_plugin .EventListener ):
18256
57+ class SublimeJavaCompletion (completioncommon .CompletionCommon ):
18358 def __init__ (self ):
184- self .cache_list = []
185-
186- def find_absolute_of_type (self , data , full_data , type ):
187- thispackage = re .search ("[ \t ]*package (.*);" , data )
188- if thispackage is None :
189- thispackage = ""
190- else :
191- thispackage = thispackage .group (1 )
59+ super (SublimeJavaCompletion , self ).__init__ ("SublimeJava.sublime-settings" , os .path .dirname (os .path .abspath (__file__ )))
60+ self .javaseparator = None # just so that get_cmd references it. It's set "for real" later
61+ self .javaseparator = self .run_completion ("-separator" ).strip ()
19262
193- match = re .search ("class %s" % type , full_data )
194- if not match is None :
195- # This type is defined in this file so figure out the nesting
196- full_data = parsehelp .remove_empty_classes (parsehelp .remove_preprocessing (parsehelp .collapse_brackets (full_data [:match .start ()])))
197- regex = re .compile ("\s*class\s+([^\\ s{]+)" )
198- add = ""
199- for m in re .finditer (regex , full_data ):
200- if len (add ):
201- add = "%s$%s" % (add , m .group (1 ))
202- else :
203- add = m .group (1 )
63+ def get_cmd (self ):
64+ classpath = "."
65+ if self .javaseparator != None :
66+ classpath = self .get_setting ("sublimejava_classpath" , ["." ])
67+ classpath .append ("." )
68+ classpath = self .javaseparator .join (classpath )
69+ return "java -classpath %s SublimeJava" % classpath
20470
205- if len (add ):
206- type = "%s$%s" % (add , type )
207- # Class is defined in this file, return package of the file
208- if len (thispackage ) == 0 :
209- return type
210- return "%s.%s" % (thispackage , type )
71+ def is_supported_language (self , view ):
72+ if view .is_scratch () or not self .get_setting ("sublimejava_enabled" , True ):
73+ return False
74+ language = self .get_language (view )
75+ return language == "java" or language == "jsp"
21176
212- packages = re .findall ("[ \t ]*import[ \t ]+(.*);" , data )
213- packages .append ("java.lang.*" )
214- packages .append (thispackage + ".*" )
215- packages .append ("" ) # for int, boolean, etc
216- for package in packages :
217- if package .endswith (".%s" % type ):
218- # Explicit imports, we want these to have the highest
219- # priority when searching for the absolute type, so
220- # insert them at the top of the package list.
221- # Both the .* version and not is added so that
222- # blah.<searchedForClass> and blah$<searchedForClass>
223- # is tested
224- add = package [:- (len (type )+ 1 )]
225- packages .insert (0 , add + ".*" )
226- packages .insert (1 , add )
227- break
228- packages .append (";;--;;" )
77+ comp = SublimeJavaCompletion ()
22978
230- output = run_java ("-findclass %s" % (type ), "\n " .join (packages )).strip ()
231- if len (output ) == 0 and "." in type :
232- return self .find_absolute_of_type (data , full_data , type .replace ("." , "$" ))
233- return output
23479
235- def complete_class (self , absolute_classname , prefix ):
236- stdout = run_java ("-complete %s %s" % (absolute_classname , prefix ))
237- stdout = stdout .split ("\n " )[:- 2 ]
238- members = [tuple (line .split (";;--;;" )) for line in stdout ]
239- ret = []
240- for member in members :
241- if member not in ret :
242- ret .append (member )
243- return sorted (ret , key = lambda a : a [0 ])
244-
245- def get_return_type (self , absolute_classname , prefix ):
246- stdout = run_java ("-returntype %s %s" % (absolute_classname , prefix ))
247- ret = stdout .strip ()
248- match = re .search ("(\[L)?([^;]+)" , ret )
249- if match :
250- return match .group (2 )
251- return ret
80+ class SublimeJava (sublime_plugin .EventListener ):
25281
25382 def on_query_completions (self , view , prefix , locations ):
254- bs = time .time ()
255- start = time .time ()
256- if not is_supported_language (view ):
257- return []
258- line = view .substr (sublime .Region (view .full_line (locations [0 ]).begin (), locations [0 ]))
259- before = line
260- if len (prefix ) > 0 :
261- before = line [:- len (prefix )]
262- if re .search ("[ \t ]+$" , before ):
263- before = ""
264- elif re .search ("\.$" , before ):
265- # Member completion
266- data = view .substr (sublime .Region (0 , locations [0 ]))
267- full_data = view .substr (sublime .Region (0 , view .size ()))
268- typedef = parsehelp .get_type_definition (data , before )
269- if typedef == None :
270- return []
271- line , column , typename , var , tocomplete = typedef
272-
273- if typename is None :
274- # This is for completing for example "System."
275- # or "String." or other static calls/variables
276- typename = var
277- start = time .time ()
278- typename = re .sub ("(<.*>)|(\[.*\])" , "" , typename )
279- typename = self .find_absolute_of_type (data , full_data , typename )
280- end = time .time ()
281- print "absolute is %s (%f ms)" % (typename , (end - start )* 1000 )
282- if typename == "" :
283- return []
284-
285- tocomplete = tocomplete [1 :] # skip initial .
286- start = time .time ()
287- idx = tocomplete .find ("." )
288- while idx != - 1 :
289- sub = tocomplete [:idx ]
290- idx2 = sub .find ("(" )
291- if idx2 >= 0 :
292- sub = sub [:idx2 ]
293- count = 1
294- for i in range (idx + 1 , len (tocomplete )):
295- if tocomplete [i ] == '(' :
296- count += 1
297- elif tocomplete [i ] == ')' :
298- count -= 1
299- if count == 0 :
300- idx = tocomplete .find ("." , i )
301- break
302-
303- n = self .get_return_type (typename , sub )
304- print "%s.%s = %s" % (typename , sub , n )
305- typename = n
306- tocomplete = tocomplete [idx + 1 :]
307- idx = tocomplete .find ("." )
308- end = time .time ()
309- print "finding what to complete took %f ms" % ((end - start ) * 1000 )
310-
311- print "completing %s.%s" % (typename , prefix )
312- start = time .time ()
313- ret = self .complete_class (typename , prefix )
314- end = time .time ()
315- print "completion took %f ms" % ((end - start )* 1000 )
316- be = time .time ()
317- print "total %f ms" % ((be - bs )* 1000 )
318- return ret
319-
320- print "here"
321- return []
83+ return comp .on_query_completions (view , prefix , locations )
32284
32385 def on_query_context (self , view , key , operator , operand , match_all ):
32486 if key == "sublimejava.dotcomplete" :
325- return get_setting (key .replace ("." , "_" ), True )
87+ return comp . get_setting (key .replace ("." , "_" ), True )
32688 elif key == "sublimejava.supported_language" :
327- return is_supported_language (view )
328- elif key == "sublimejava.is_code" :
329- caret = view .sel ()[0 ].a
330- scope = view .scope_name (caret ).strip ()
331- return re .search ("(string.)|(comment.)" , scope ) == None
89+ return comp .is_supported_language (view )
90+ else :
91+ return comp .on_query_context (view , key , operator , operand , match_all )
0 commit comments