Skip to content

Commit a651c77

Browse files
committed
Now based on the new "sublimecompletioncommon" module
1 parent ca98b81 commit a651c77

7 files changed

Lines changed: 34 additions & 269 deletions

File tree

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "parsehelp"]
22
path = parsehelp
33
url = git://github.com/quarnster/parsehelp.git
4+
[submodule "sublimecompletioncommon"]
5+
path = sublimecompletioncommon
6+
url = git://github.com/quarnster/SublimeCompletionCommon.git

Default.sublime-keymap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[
66
{"key": "sublimejava.supported_language"},
77
{"key": "sublimejava.dotcomplete"},
8-
{"key": "sublimejava.is_code"}
8+
{"key": "completion_common.is_code"}
99
]
1010
}
1111
]

README.creole

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Please go [[https://github.com/quarnster/SublimeJava/issues?sort=created&directi
1212
* You need to manually install it using git
1313
** Go to your packages directory and type:
1414
*** git clone --recursive https://github.com/quarnster/SublimeJava SublimeJava
15+
** To update to the latest commit, use this command in the SublimeJava directory:
16+
*** git pull && git submodule update --init
1517
* You most likely want to configure the "sublimejava_classpath" setting to your own, issue [[https://github.com/quarnster/SublimeJava/issues/23|23]] details how this is done.
1618
1719
=== Usage ===

SublimeJava.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ else if (args[0].equals("-returntype"))
283283
}
284284
catch (Exception e)
285285
{
286-
System.err.println("Exception caugth: " + e.getMessage());
286+
System.err.println("Exception caught: " + e.getMessage());
287287
e.printStackTrace(System.err);
288288
}
289289
}

parsehelp

Submodule parsehelp deleted from 78eb7d9

sublimecompletioncommon

Submodule sublimecompletioncommon added at ea117a4

sublimejava.py

Lines changed: 26 additions & 266 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,9 @@
2222
"""
2323
import sublime
2424
import sublime_plugin
25-
import re
26-
import subprocess
2725
import os.path
28-
import time
29-
import os
30-
import Queue
31-
import threading
3226
try:
33-
from parsehelp import parsehelp
27+
from sublimecompletioncommon import completioncommon
3428
except:
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

Comments
 (0)