示例#1
0
    def args_to_clang_cc1(self, data, args, directory):
        # Translate to clang args
        # clang-5.0 -### -x c++  -c -
        cmd = [data['clang_path'], '-###'] + args + ['-']
        logger.debug('to clang cc1 cmd: %s', cmd)

        proc = Popen(args=cmd,
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)

        outdata, errdata = proc.communicate('', timeout=2)
        logger.debug('outdata: %s, errdata: %s', outdata, errdata)
        if proc.returncode != 0:
            return None

        errdata = errdata.decode()

        lines = errdata.splitlines()
        installed_dir_found = False
        for line in lines:
            if not installed_dir_found:
                if line.startswith('InstalledDir:'):
                    installed_dir_found = True
                continue
            args = shlex.split(line)
            # remove clang binary and the last '-', insert working directory
            # after -cc1
            args = args[1:-1]
            args.insert(1, '-working-directory=' + directory)
            logger.debug('-cc1 args: %s', args)
            return args

        return None
示例#2
0
    def get_system_include(self, gcc, args):

        # $ gcc -xc++ -E -Wp,-v -
        # ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/7"
        # ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
        # ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/7/../../../../x86_64-linux-gnu/include"
        # #include "..." search starts here:
        # #include <...> search starts here:
        #  /usr/include/c++/7
        #  /usr/include/x86_64-linux-gnu/c++/7
        #  /usr/include/c++/7/backward
        #  /usr/lib/gcc/x86_64-linux-gnu/7/include
        #  /usr/local/include
        #  /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
        #  /usr/include/x86_64-linux-gnu
        #  /usr/include
        # End of search list.
        args += ['-E', '-Wp,-v', '-']

        gcc_is_cygwin = sys.platform == 'win32'

        # Gcc is installed on Cygwin or MinGW, we need to prefix the include
        # directories with cygwin/mingw base path
        prefix = ''
        if gcc_is_cygwin:
            gcc_dir = dirname(gcc)
            if gcc_dir.endswith('\\usr\\bin'):
                prefix = gcc_dir[:len(gcc_dir) - len('usr\\bin')]
            elif gcc_dir.endswith('\\bin'):
                prefix = gcc_dir[:len(gcc_dir) - len('bin')]

        proc = Popen(args=[gcc] + args,
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)

        outdata, errdata = proc.communicate('', timeout=2)

        errdata = errdata.decode()

        lines = errdata.split('\n')

        res = []
        for line in lines:
            if line.startswith(' /'):
                inc_dir = line.strip()
                res += ['-isystem', prefix + inc_dir]
                # cygwin uses symlink /usr/lib -> /lib, the directory cannot be
                # accessed with Windows file explorer
                if gcc_is_cygwin and inc_dir.startswith('/usr/lib/'):
                    res += [
                        '-isystem',
                        prefix + inc_dir.replace('/usr/lib/', '/lib/')
                    ]

        logger.debug('system include: %s', res)
        return res
示例#3
0
    def get_repo_user(self, cwd):
        args = ['git', 'remote', '-v']
        try:
            proc = Popen(args=args,
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.DEVNULL,
                         cwd=cwd)
            result, errs = proc.communicate('', 10)
            result = result.decode('utf-8')
            match = self.repo_user_pat.search(result)
            if not match:
                return None, None

            return match.group(1), match.group(2)
        except Exception:
            logger.exception("Failed executing _get_repo_user at cwd [%s]",
                             cwd)
            return None, None
示例#4
0
    def on_complete(self, ctx):
        base = ctx['base']
        filepath = ctx['filepath']
        matcher = self.matcher_get(ctx)

        try:
            command = self.command + [self.optfile, filepath]

            proc = Popen(args=command,
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
            outs, errs = proc.communicate(timeout=Source.PROC_TIMEOUT)

            if errs:
                raise SourceException(errs.decode('utf-8'))

            candidates = outs.decode('utf-8').splitlines()
            candidates = self.matches_formalize(ctx, candidates)

            if candidates:
                self.candidates = candidates
                logger.info('Found %s "%s" completion candidates',
                            len(self.candidates), self.name)
        except SourceException as err:
            logger.error('Error collecting "%s" candidates', self.name)
            logger.error(err)
        except TimeoutExpired as err:
            proc.kill()
            logger.exception('Error collecting "%s" candidates', self.name)
        except Exception as err:
            logger.exception('Error collecting "%s" candidates', self.name)

        matches = [
            candidate for candidate in self.candidates
            if matcher(base, candidate)
        ]
        logger.info('Found %s "%s" completion matches', len(matches),
                    self.name)
        self.complete(ctx, ctx['startccol'], matches, True)
示例#5
0
    def __init__(self, nvim):
        Ncm2Source.__init__(self, nvim)

        this_file = path.abspath(__file__)
        basedir = path.dirname(this_file)
        basedir = path.dirname(basedir)

        ncm_libclang_bin = nvim.vars['ncm2_libclang#bin']
        if type(ncm_libclang_bin) == str:
            ncm_libclang_bin = [ncm_libclang_bin]

        ncm_libclang_bin[0] = path.join(basedir, ncm_libclang_bin[0])

        if not path.isfile(ncm_libclang_bin[0]):
            raise Exception("%s doesn't exist, please compile it" %
                            ncm_libclang_bin[0])

        self.proc = Popen(args=ncm_libclang_bin,
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.DEVNULL)

        nvim.command("call ncm2_libclang#on_warmup(ncm2#context())",
                     async_=True)
示例#6
0
    def on_complete(self, ctx, lines, cwd, phpactor_complete):
        src = "\n".join(lines)
        src = self.get_src(src, ctx)

        lnum = ctx['lnum']

        # use byte addressing
        bcol = ctx['bcol']
        src = src.encode()

        pos = self.lccol2pos(lnum, bcol, src)
        args = phpactor_complete
        args += [str(pos)]

        proc = Popen(args=args,
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.DEVNULL)

        result, errs = proc.communicate(src, timeout=5)

        result = result.decode()

        logger.debug("args: %s, result: [%s]", args, result)

        result = json.loads(result)

        # {
        #     "suggestions": [
        #         {
        #             "type": "f",
        #             "name": "setFormatter",
        #             "info": "pub setFormatter(OutputFormatterInterface $formatter)"
        #         }
        #     ]
        # }

        matches = []

        for e in result['suggestions']:
            menu = e['info']
            word = e['name']
            t = e['type']

            item = dict(word=word, menu=menu)

            # snippet support
            m = re.search(r'(\w+\s+)?\w+\((.*)\)', menu)

            if m and (t == 'function' or t == 'method'):

                params = m.group(2)

                placeholders = []
                num = 1
                snip_args = ''

                if params != '':

                    params = params.split(',')

                    for param in params:

                        if "=" in param:
                            # skip params with default value
                            break
                        else:
                            param = re.search(r'\$\w+', param).group()
                            ph = self.snippet_placeholder(num, param)
                            placeholders.append(ph)
                            num += 1

                    snip_args = ', '.join(placeholders)

                    if len(placeholders) == 0:
                        # don't jump out of parentheses if function has
                        # parameters
                        snip_args = self.snippet_placeholder(1)

                ph0 = self.snippet_placeholder(0)
                snippet = '%s(%s)%s' % (word, snip_args, ph0)

                item['user_data'] = {'snippet': snippet, 'is_snippet': 1}

            matches.append(item)

        self.complete(ctx, ctx['startccol'], matches)
示例#7
0
    def on_complete(self, ctx, lines):
        src = "\n".join(lines)
        src = self.get_src(src, ctx)
        src = src.encode('utf-8')
        lnum = ctx['lnum']
        ccol = ctx['ccol']
        bcol = ctx['bcol']
        typed = ctx['typed']
        filepath = ctx['filepath']
        startccol = ctx['startccol']

        query = typed.lstrip(" \t\'\"")
        # args = ['elm-oracle', filepath, query]

        args = [
            'elm-oracle',
            str(lnum),
            str(bcol - 1),
            filepath,
            '-',
            query
        ]

        proj_dir = self._project_root(filepath)
        proc = Popen(
            args=args,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.DEVNULL
            cwd=proj_dir)

        result, errs = proc.communicate(src, timeout=30)
        result = json.loads(result.decode('utf-8'))

        logger.debug("args: %s, result: [%s]", args, result.decode())

        if not result:
            return

        matches = []

        # for line in lines:
        #     fields = line.split(";")
        #     tword = fields[0].split(' ')

        #     if tword[0] != "MATCH":
        #         if tword == "prefix":
        #             startccol = ccol - len(fields[2])
        #         continue

        #     t, word = tword

        #     match = dict(word=word)

        #     menu = fields[6]

        #     match['menu'] = menu
        #     match = self.match_formalize(ctx, match)

        #     snippet = fields[1]
        #     if snippet != word:
        #         ud = match['user_data']
        #         ud['is_snippet'] = 1
        #         ud['snippet'] = snippet

        #     matches.append(match)

        for item in result:
            word = item['name']
            menu = item.get('signature', item.get('fullName',''))
            m = { 'word': word, 'menu': menu, 'info': item['comment'] }

            matches.append(m)


        logger.info("matches: [%s]", matches)

        self.complete(ctx, startccol, matches)
示例#8
0
    def on_complete(self, ctx, lines):

        src = "\n".join(lines)
        src = self.get_src(src, ctx)
        src = src.encode('utf-8')
        lnum = ctx['lnum']
        ccol = ctx['ccol']
        bcol = ctx['bcol']
        filepath = ctx['filepath']
        startccol = ctx['startccol']

        args = [
            'racer', 'complete-with-snippet',
            str(lnum),
            str(bcol - 1), filepath, '-'
        ]
        proc = Popen(args=args,
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.DEVNULL)

        result, errs = proc.communicate(src, timeout=30)

        logger.debug("args: %s, result: [%s]", args, result.decode())

        lines = result.decode('utf-8').splitlines()

        # typical output example:
        #   PREFIX 47,51,Stri
        #   MATCH String;String;263;11;/data/roxma/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/../libcollections/string.rs;Struct;pub struct String;"A UTF-8 encoded, growable string.\n\nThe `String` type is the most common string type that has ownership over the\ncontents of the string. It has a close relationship with its borrowed\ncounterpart, the primitive [`str`].\n\n[`str`]: ../../std/primitive.str.html\n\n# Examples\n\nYou can create a `String` from a literal string with `String::from`:\n\n```\nlet hello = String::from(\"Hello, world!\")\;\n```\n\nYou can append a [`char`] to a `String` with the [`push()`] method, and\nappend a [`&str`] with the [`push_str()`] method:\n\n```\nlet mut hello = String::from(\"Hello, \")\;\n\nhello.push(\'w\')\;\nhello.push_str(\"orld!\")\;\n```\n\n[`char`]: ../../std/primitive.char.html\n[`push()`]: #method.push\n[`push_str()`]: #method.push_str\n\nIf you have a vector of UTF-8 bytes, you can create a `String` from it with\nthe [`from_utf8()`] method:\n\n```\n// some bytes, in a vector\nlet sparkle_heart = vec![240, 159, 146, 150]\;\n\n// We know these bytes are valid, so we\'ll use `unwrap()`.\nlet sparkle_heart = String::from_utf8(sparkle_heart).unwrap()\;\n\nassert_eq!(\"💖\", sparkle_heart)\;\n```\n\n[`from_utf8()`]: #method.from_utf8\n\n# UTF-8\n\n`String`s are always valid UTF-8. This has a few implications, the first of\nwhich is that if you need a non-UTF-8 string, consider [`OsString`]. It is\nsimilar, but without the UTF-8 constraint. The second implication is that\nyou cannot index into a `String`:\n\n```ignore\nlet s = \"hello\"\;\n\nprintln!(\"The first letter of s is {}\", s[0])\; // ERROR!!!\n```\n\n[`OsString`]: ../../std/ffi/struct.OsString.html\n\nIndexing is intended to be a constant-time operation, but UTF-8 encoding\ndoes not allow us to do this. Furthermore, it\'s not clear what sort of\nthing the index should return: a byte, a codepoint, or a grapheme cluster.\nThe [`bytes()`] and [`chars()`] methods return iterators over the first\ntwo, respectively.\n\n[`bytes()`]: #method.bytes\n[`chars()`]: #method.chars\n\n# Deref\n\n`String`s implement [`Deref`]`<Target=str>`, and so inherit all of [`str`]\'s\nmethods. In addition, this means that you can pass a `String` to any\nfunction which takes a [`&str`] by using an ampersand (`&`):\n\n```\nfn takes_str(s: &str) { }\n\nlet s = String::from(\"Hello\")\;\n\ntakes_str(&s)\;\n```\n\n[`&str`]: ../../std/primitive.str.html\n[`Deref`]: ../../std/ops/trait.Deref.html\n\nThis will create a [`&str`] from the `String` and pass it in. This\nconversion is very inexpensive, and so generally, functions will accept\n[`&str`]s as arguments unless they need a `String` for some specific reason.\n\n\n# Representation\n\nA `String` is made up of three components: a pointer to some bytes, a\nlength, and a capacity. The pointer points to an internal buffer `String`\nuses to store its data. The length is the number of bytes currently stored\nin the buffer, and the capacity is the size of the buffer in bytes. As such,\nthe length will always be less than or equal to the capacity.\n\nThis buffer is always stored on the heap.\n\nYou can look at these with the [`as_ptr()`], [`len()`], and [`capacity()`]\nmethods:\n\n```\nuse std::mem\;\n\nlet story = String::from(\"Once upon a time...\")\;\n\nlet ptr = story.as_ptr()\;\nlet len = story.len()\;\nlet capacity = story.capacity()\;\n\n// story has nineteen bytes\nassert_eq!(19, len)\;\n\n// Now that we have our parts, we throw the story away.\nmem::forget(story)\;\n\n// We can re-build a String out of ptr, len, and capacity. This is all\n// unsafe because we are responsible for making sure the components are\n// valid:\nlet s = unsafe { String::from_raw_parts(ptr as *mut _, len, capacity) } \;\n\nassert_eq!(String::from(\"Once upon a time...\"), s)\;\n```\n\n[`as_ptr()`]: #method.as_ptr\n[`len()`]: #method.len\n[`capacity()`]: #method.capacity\n\nIf a `String` has enough capacity, adding elements to it will not\nre-allocate. For example, consider this program:\n\n```\nlet mut s = String::new()\;\n\nprintln!(\"{}\", s.capacity())\;\n\nfor _ in 0..5 {\n    s.push_str(\"hello\")\;\n    println!(\"{}\", s.capacity())\;\n}\n```\n\nThis will output the following:\n\n```text\n0\n5\n10\n20\n20\n40\n```\n\nAt first, we have no memory allocated at all, but as we append to the\nstring, it increases its capacity appropriately. If we instead use the\n[`with_capacity()`] method to allocate the correct capacity initially:\n\n```\nlet mut s = String::with_capacity(25)\;\n\nprintln!(\"{}\", s.capacity())\;\n\nfor _ in 0..5 {\n    s.push_str(\"hello\")\;\n    println!(\"{}\", s.capacity())\;\n}\n```\n\n[`with_capacity()`]: #method.with_capacity\n\nWe end up with a different output:\n\n```text\n25\n25\n25\n25\n25\n25\n```\n\nHere, there\'s no need to allocate more memory inside the loop."
        #   END
        # another example(`String::`)
        #   PREFIX 55,55,
        #   MATCH new;new();352;11;/data/roxma/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/../libcollections/string.rs;Function;pub fn new() -> String;"Creates a new empty `String`.\n\nGiven that the `String` is empty, this will not allocate any initial\nbuffer. While that means that this initial operation is very\ninexpensive, but may cause excessive allocation later, when you add\ndata. If you have an idea of how much data the `String` will hold,\nconsider the [`with_capacity()`] method to prevent excessive\nre-allocation.\n\n[`with_capacity()`]: #method.with_capacity\n\n# Examples\n\nBasic usage:\n\n```\nlet s = String::new()\;\n```"
        #   MATCH with_capacity;with_capacity(${1:capacity});395;11;/data/roxma/.multirust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/../libcollections/string.rs;Function;pub fn with_capacity(capacity: usize) -> String;"Creates a new empty `String` with a particular capacity.\n\n`String`s have an internal buffer to hold their data. The capacity is\nthe length of that buffer, and can be queried with the [`capacity()`]\nmethod. This method creates an empty `String`, but one with an initial\nbuffer that can hold `capacity` bytes. This is useful when you may be\nappending a bunch of data to the `String`, reducing the number of\nreallocations it needs to do.\n\n[`capacity()`]: #method.capacity\n\nIf the given capacity is `0`, no allocation will occur, and this method\nis identical to the [`new()`] method.\n\n[`new()`]: #method.new\n\n# Examples\n\nBasic usage:\n\n```\nlet mut s = String::with_capacity(10)\;\n\n// The String contains no chars, even though it has capacity for more\nassert_eq!(s.len(), 0)\;\n\n// These are all done without reallocating...\nlet cap = s.capacity()\;\nfor i in 0..10 {\n    s.push(\'a\')\;\n}\n\nassert_eq!(s.capacity(), cap)\;\n\n// ...but this may make the vector reallocate\ns.push(\'a\')\;\n```"
        #   END
        matches = []
        for line in lines:

            fields = line.split(";")
            tword = fields[0].split(' ')

            if tword[0] != "MATCH":
                if tword == "prefix":
                    startccol = ccol - len(fields[2])
                continue

            t, word = tword

            match = dict(word=word)

            menu = fields[6]
            if "RUST_SRC_PATH" in os.environ and menu.startswith(
                    os.environ["RUST_SRC_PATH"]):
                menu = menu[len(os.environ["RUST_SRC_PATH"]):]

            match['menu'] = menu
            match = self.match_formalize(ctx, match)

            snippet = fields[1]
            if snippet != word:
                ud = match['user_data']
                ud['is_snippet'] = 1
                ud['snippet'] = snippet

            matches.append(match)

        logger.info("matches: [%s]", matches)

        self.complete(ctx, startccol, matches)
示例#9
0
    def on_complete(self, ctx, extension, lines):
        if not extension:
            extension = '0'

        matches = []

        src = "\n".join(lines)
        src = self.get_src(src, ctx)

        lnum = ctx['lnum']

        # use byte addressing
        bcol = ctx['bcol']
        src = src.encode()

        pos = self.lccol2pos(lnum, bcol, src)

        # get the php autocomplete bin path
        dir_path = os.path.dirname(os.path.realpath(__file__))
        autocomplete_bin_path = dir_path + '/../bin/app.php'

        args = [
            'php', autocomplete_bin_path, 'complete', '-d',
            os.getcwd(), '-p',
            str(pos), '-e', extension
        ]
        #args = ['php', autocomplete_bin_path, '-d', os.getcwd(), str(pos)]
        proc = Popen(args=args,
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.DEVNULL)

        result, errs = proc.communicate(src, timeout=self.completion_timeout)

        result = result.decode()

        logger.debug("extension: %s", extension)

        logger.debug("args: %s", args)
        #logger.debug("result: [%s]", result)

        #logger.debug(result)
        result = json.loads(result)

        if not result or not result.get('suggestions', None):
            logger.debug('No matches found...abort')
            return

        matches = []
        for e in result['suggestions']:
            shortDescription = e['short_description']
            word = e['name']
            #t = e['type']

            #item = {'word': word, 'menu': menu, 'info': menu}
            item = dict(word=word,
                        menu=shortDescription,
                        info=shortDescription)

            #snip_args = 'args'
            #ph0 = '${%s:%s}' % ('num', 'txt')

            #snippet = '%s(%s)%s' % (word, snip_args, ph0)

            #item['user_data'] = {'snippet': snippet, 'is_snippet': 1}
            matches.append(item)

        self.complete(ctx, ctx['startccol'], matches)