aboutsummaryrefslogtreecommitdiffstats
path: root/python/vhdl_langserver/main.py
blob: 0759043e69a92833b0f56ff285948a184af1f4f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python
from __future__ import absolute_import

import argparse
import logging
import sys
import os

import libghdl
import libghdl.thin.errorout_console

from . import version
from . import lsp
from . import vhdl_ls

logger = logging.getLogger('ghdl-ls')


class LSPConnTrace(object):
    """Wrapper class to save in and out packets"""
    def __init__(self, basename, conn):
        self.conn = conn
        self.trace_in = open(basename + '.in', 'w')
        self.trace_out = open(basename + '.out', 'w')

    def readline(self):
        res = self.conn.readline()
        self.trace_in.write(res)
        return res

    def read(self, size):
        res = self.conn.read(size)
        self.trace_in.write(res)
        self.trace_in.flush()
        return res

    def write(self, out):
        self.conn.write(out)
        self.trace_out.write(out)
        self.trace_out.flush()


def rotate_log_files(basename, num):
    for i in range(num, 0, -1):
        oldfile = '{}.{}'.format(basename, i - 1)
        if os.path.isfile(oldfile):
            os.rename(oldfile, '{}.{}'.format(basename, i))
    if os.path.isfile(basename):
        os.rename(basename, '{}.0'.format(basename))


def main():
    parser = argparse.ArgumentParser(
        description='VHDL Language Protocol Server')
    parser.add_argument(
        '--version', '-V', action='version', version='%(prog)s ' + version.__version__)
    parser.add_argument(
        '--verbose', '-v', action='count', default=0,
        help='Show debug output')
    parser.add_argument(
        '--log-file',
        help="Redirect logs to the given file instead of stderr")
    parser.add_argument(
        '--trace-file',
        help="Save rpc data to FILE.in and FILE.out")
    parser.add_argument(
        '--input', '-i',
        help="Read request from file")
    parser.add_argument(
        '--disp-config', action='store_true', help="Disp installation configuration and exit")

    args = parser.parse_args()

    if args.disp_config:
        libghdl.thin.errorout_console.Install_Handler()
        libghdl.disp_config()
        return

    # Setup logging
    if args.verbose >= 2:
        loglevel = logging.DEBUG
    elif args.verbose >= 1:
        loglevel = logging.INFO
    else:
        loglevel = logging.ERROR

    if args.log_file:
        rotate_log_files(args.log_file, 5)
        logstream = open(args.log_file, 'w')
    else:
        logstream = sys.stderr
    logging.basicConfig(format='%(asctime)-15s [%(levelname)s] %(message)s',
                        stream=logstream, level=loglevel)

    if args.verbose != 0:
        sys.stderr.write('Args: {}\n'.format(sys.argv))
        sys.stderr.write('Current directory: {}\n'.format(os.getcwd()))

    logger.info('Args: %s', sys.argv)
    logger.info('Current directory is %s', os.getcwd())

    # Connection
    instream = sys.stdin.buffer
    if args.input is not None:
        instream = open(args.input, 'rb')

    conn = lsp.LSPConn(instream, sys.stdout.buffer)

    trace_file = args.trace_file
    if trace_file is None:
        trace_file = os.environ.get('GHDL_LS_TRACE')
    if trace_file is not None:
        if args.input is None:
            rotate_log_files(trace_file + '.in', 5)
            rotate_log_files(trace_file + '.out', 5)
            conn = LSPConnTrace(trace_file, conn)
        else:
            logger.info('Traces disabled when -i/--input')

    handler = vhdl_ls.VhdlLanguageServer()

    try:
        server = lsp.LanguageProtocolServer(handler, conn)
        server.run()
    except Exception:
        logger.exception('Uncaught error')
        sys.exit(1)