kopia lustrzana https://github.com/c9/core
206 wiersze
7.3 KiB
Python
Executable File
206 wiersze
7.3 KiB
Python
Executable File
import argparse
|
|
import json
|
|
import sys
|
|
import os
|
|
import logging
|
|
from os import path
|
|
import urlparse
|
|
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
|
|
|
# Hackfix codeintel import
|
|
sys.path.extend([p + "/codeintel" for p in sys.path])
|
|
|
|
# Hackfix inflector compatibility
|
|
import inflector
|
|
class MyInflector: Inflector = inflector.Inflector
|
|
class MyInflector2: Inflector = MyInflector
|
|
sys.modules["inflector.Inflector"] = MyInflector2
|
|
sys.modules["inflector"] = MyInflector2
|
|
import inflector.Inflector
|
|
|
|
from codeintel2.common import EvalController
|
|
from codeintel2.manager import Manager
|
|
from codeintel2.environment import DefaultEnvironment
|
|
|
|
def main(args):
|
|
if args.mode != "daemon":
|
|
print(process(sys.stdin.read(), args.__dict__))
|
|
manager.finalize()
|
|
return
|
|
try:
|
|
server = HTTPServer(("localhost", int(args.port)), Daemon)
|
|
except:
|
|
sys.stderr.write("Daemon unable to listen at :%s\n" % args.port)
|
|
sys.exit(98)
|
|
sys.stderr.write("!!Daemon " + "listening at :%s\n" % args.port) # concat strings to avoid matching this string in the client
|
|
server.serve_forever()
|
|
|
|
def process(source, args):
|
|
mode = args["mode"]
|
|
buffer, line, offset = process_input(source, args)
|
|
scan_workspace(buffer)
|
|
|
|
if mode == "completions":
|
|
return json.dumps(get_completions(buffer, line, offset))
|
|
if mode == "definitions":
|
|
return json.dumps(get_definitions(buffer, line, offset))
|
|
if mode == "calltips":
|
|
return json.dumps(get_calltips(buffer, line, offset))
|
|
if mode == "catalogs":
|
|
return json.dumps(get_catalogs(buffer, line, offset))
|
|
|
|
def get_completions(buffer, line, offset):
|
|
trigger = buffer.preceding_trg_from_pos(offset, offset)
|
|
if trigger is None:
|
|
return []
|
|
results = buffer.cplns_from_trg(trigger, ctlr = LoggingEvalController(), timeout = 120)
|
|
if results is None:
|
|
return []
|
|
return [
|
|
remove_nulls({
|
|
"name": get_proposal_name(kind, name, buffer.lang, trigger),
|
|
"replaceText": get_proposal_replace_text(kind, name, buffer.lang, trigger, line),
|
|
"icon": {
|
|
"function": "method",
|
|
"module": "package",
|
|
"class": "package",
|
|
"element": "event",
|
|
"property": "property",
|
|
"value": "method",
|
|
}.get(kind, "property"),
|
|
}) for kind, name in results
|
|
]
|
|
|
|
def get_definitions(buffer, line, offset):
|
|
trigger = buffer.defn_trg_from_pos(offset)
|
|
if trigger is None:
|
|
return []
|
|
results = buffer.defns_from_trg(trigger, ctlr = LoggingEvalController(), timeout = 10)
|
|
if results is None:
|
|
return []
|
|
return {
|
|
"path": "/" + results[0].path,
|
|
"row": results[0].line - 1,
|
|
}
|
|
|
|
def get_calltips(buffer, line, offset):
|
|
trigger = buffer.preceding_trg_from_pos(offset, offset)
|
|
if trigger is None:
|
|
return []
|
|
result = buffer.calltips_from_trg(trigger, ctlr = LoggingEvalController(), timeout = 10)
|
|
if result is None:
|
|
return ""
|
|
return result
|
|
|
|
def get_catalogs(buffer, line, offset):
|
|
return [c for c in manager.db.get_catalogs_zone().avail_catalogs()]
|
|
|
|
def get_proposal_name(kind, name, lang, trigger):
|
|
if lang == "PHP" and kind == "variable" and trigger.name != "php-complete-object-members":
|
|
return "$" + name
|
|
if kind == "function" or kind == "method":
|
|
return name + "()"
|
|
return name
|
|
|
|
def get_proposal_replace_text(kind, name, lang, trigger, line):
|
|
if lang == "PHP" and kind == "variable" and trigger.name != "php-complete-object-members":
|
|
return "$" + name
|
|
if "import " in line:
|
|
return name
|
|
if kind == "function" or kind == "method":
|
|
return name + "(^^)"
|
|
|
|
def remove_nulls(d):
|
|
for key, value in d.items():
|
|
if value is None:
|
|
del d[key]
|
|
elif isinstance(value, dict):
|
|
remove_nulls(value)
|
|
return d
|
|
|
|
def process_input(source, args):
|
|
row = int(args.get("row"))
|
|
column = int(args.get("column"))
|
|
path = args.get("path")
|
|
basedir = args.get("basedir")
|
|
language = args.get("language")
|
|
dirs = args.get("dirs")
|
|
catalogs = args.get("catalogs").split(",") if args.get("catalogs") else []
|
|
|
|
env = manager.env = DefaultEnvironment()
|
|
env.set_pref("codeintel_selected_catalogs", catalogs)
|
|
env.set_pref("extra_module_dirs", dirs)
|
|
env.set_pref("phpExtraPaths", dirs)
|
|
env.set_pref("codeintel_scan_extra_dir", dirs)
|
|
env.set_pref("codeintel_scan_files_in_project", True)
|
|
|
|
env.get_proj_base_dir = lambda: basedir
|
|
buffer = manager.buf_from_content(source + "\n", language, path = path, env = env)
|
|
lines = source.split('\n')
|
|
line = lines[row]
|
|
offset = sum([len(l) + 1 for l in lines[:row]]) + column
|
|
return buffer, line, offset
|
|
|
|
def scan_workspace(buffer):
|
|
if not manager.is_citadel_lang(buffer.lang):
|
|
return
|
|
if not buffer.lang in scanned_langs:
|
|
sys.stderr.write("!!Updating " + buffer.lang + " indexes\n")
|
|
scanned_langs.append(buffer.lang)
|
|
buffer.scan()
|
|
sys.stderr.write("!!Done updating indexes\n")
|
|
manager.db.save()
|
|
else:
|
|
buffer.scan()
|
|
|
|
class LoggingEvalController(EvalController):
|
|
def debug(self, msg, *args): logger.debug(msg, *args)
|
|
def info(self, msg, *args): logger.info(msg, *args)
|
|
def warn(self, msg, *args): logger.warn(msg, *args)
|
|
def error(self, msg, *args): logger.error(msg, *args)
|
|
|
|
class Daemon(BaseHTTPRequestHandler):
|
|
def do_POST(self):
|
|
query = urlparse.urlparse(self.path).query
|
|
args = urlparse.parse_qsl(query)
|
|
|
|
length = int(self.headers.getheader("content-length", 0))
|
|
source = self.rfile.read(length)
|
|
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
self.wfile.write(process(source, dict(args)))
|
|
def log_message(self, format, *args):
|
|
return # log silently
|
|
|
|
logStream = logging.StreamHandler(sys.stderr)
|
|
logStream.setFormatter(logging.Formatter("%(name)s: %(levelname)s: %(message)s"))
|
|
logging.getLogger("codeintel").addHandler(logStream)
|
|
logger = logging.getLogger("codeintel_server")
|
|
logger.addHandler(logStream)
|
|
logger.setLevel(logging.WARNING)
|
|
|
|
manager = Manager(
|
|
# db_base_dir = path.join(CI_DIR, 'db'),
|
|
# extra_module_dirs = [path.join(CI_DIR, 'codeintel2'),],
|
|
# db_import_everything_langs = None,
|
|
# db_catalog_dirs = []
|
|
)
|
|
manager.upgrade()
|
|
manager.initialize()
|
|
scanned_langs = []
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Run codeintel commands as a daemon or via stdin")
|
|
parser.add_argument("mode", help="Mode of operation", choices=["daemon", "completions", "definitions", "calltips", "catalogs"])
|
|
parser.add_argument("--row", type=int, help="The row to read from")
|
|
parser.add_argument("--column", type=int, help="The column to read from")
|
|
parser.add_argument("--path", help="The path of the file")
|
|
parser.add_argument("--basedir", help="The basedir of the file")
|
|
parser.add_argument("--language", help="The language of the file")
|
|
parser.add_argument("--port", type=int, help="The port for the daemon to listen on")
|
|
parser.add_argument("--nodoc", help="Don't include docstrings in output")
|
|
parser.add_argument("--catalogs", help="Catalogs to include (comma-separated)")
|
|
parser.add_argument("--dirs", help="Directories to include (comma-separated)")
|
|
args = parser.parse_args()
|
|
main(args) |