Skip to content
Snippets Groups Projects
Commit d5145d0e authored by Allen, Bruce (CIV)'s avatar Allen, Bruce (CIV)
Browse files

make code check asynchronous

parent 5fa2a7d8
No related branches found
No related tags found
No related merge requests found
......@@ -3,7 +3,7 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import QPlainTextDocumentLayout
from mp_code_highlighter import MPCodeHighlighter
from mp_code_syntax_checker import mp_check_syntax
from mp_code_syntax_checker import SyntaxCheckSignaller, mp_check_syntax
# get int line number from MP Code compiler error message
def _parse_error_line_number(line):
......@@ -28,10 +28,13 @@ class MPCodeManager(QObject):
Signals:
* signal_mp_code_loaded()
* signal_syntax_error_line_number_changed()
"""
# signals
signal_mp_code_loaded = pyqtSignal(name='signalMPCodeLoaded')
signal_syntax_error_line_number_changed = pyqtSignal(
name='signalSyntaxErrroLineNumberChanged')
def __init__(self, signal_settings_changed, statusbar):
super().__init__()
......@@ -45,6 +48,9 @@ class MPCodeManager(QObject):
self.document.contentsChanged.connect(self._run_syntax_check)
self.old_mp_code_text = ""
self.syntax_check_signaler = SyntaxCheckSignaller()
self.syntax_check_signaler.signal_mp_code_syntax_checked.connect(
self._syntax_check_completed)
def set_text(self, text):
self.document.setPlainText(text)
......@@ -74,10 +80,15 @@ class MPCodeManager(QObject):
schema_name = self.highlighter.schema_name
# perform check
status = mp_check_syntax(schema_name, mp_code_text)
status = mp_check_syntax(schema_name, mp_code_text,
self.syntax_check_signaler.send_signal)
@pyqtSlot(str)
def _syntax_check_completed(self, status):
# set the error line number else 0
self.syntax_error_line_number = _parse_error_line_number(status)
self.signal_syntax_error_line_number_changed.emit()
# show status in statusbar
self.statusbar.showMessage(status)
......
from os.path import join
import threading
from subprocess import Popen, PIPE
from PyQt5.QtCore import QObject
from PyQt5.QtCore import pyqtSignal
from paths_trace_generator import trace_generator_paths
from paths_gryphon import RIGAL_SCRATCH
# use this to signal completion to GUI.
class SyntaxCheckSignaller(QObject):
"""
Signals:
signal_mp_code_syntax_checked(status)
"""
# signal "" if okay
signal_mp_code_syntax_checked = pyqtSignal(str,
name='signalMPCodeSyntaxChecked')
def __init__(self):
super().__init__()
def send_signal(self, syntax_text):
self.signal_mp_code_syntax_checked.emit(syntax_text)
# the syntax checker runs RIGAL commands in the GUI thread
def _run_rigal_now(cmd):
# the mp file must be in the same directory as the trace-generator commands
......@@ -16,46 +36,56 @@ def _run_rigal_now(cmd):
return lines
# Allow concurrency with the compiler by preserving pwd when leaving
# and expecting not to leave to service compiler state.
def mp_check_syntax(schema_name, mp_code_text):
"""Check MP Code syntax synchronously. Return "" else error which
may include the line number of ther error"""
# paths
rigal_rc = trace_generator_paths["rigal_rc"]
rigal_ic = trace_generator_paths["rigal_ic"]
# write MP Code text to file for RIGAL tools
try:
mp_filename = join(RIGAL_SCRATCH, "%s.mp" % schema_name)
with open(mp_filename, 'w') as f:
f.write(mp_code_text)
except Exception as e:
return "Error writing temporary %s.mp file: %s" % (schema_name,
str(e))
try:
# rc MP2-parser
_lines_1 = _run_rigal_now([rigal_rc, "MP2-parser"])
# rc schema
lines_2 = _run_rigal_now([rigal_ic, "MP2-parser", schema_name,
"tree", "1"])
except Exception as e:
return "Error running the trace-generator: %s"%str(e)
# maybe return error
error_lines = list()
track_errors = False
for l in lines_2:
if l[:14] == "*** error: at ":
track_errors = True
if l[:18] == "Errors detected...":
track_errors = False
if track_errors:
error_lines.append(l.strip())
# done, return any error on one line
return " ".join(error_lines)
class _SyntaxCheckerThread(threading.Thread):
def __init__(self, schema_name, mp_code_text, callback):
super().__init__()
self.schema_name = schema_name
self.mp_code_text = mp_code_text
self.callback = callback
def run(self):
# paths
rigal_rc = trace_generator_paths["rigal_rc"]
rigal_ic = trace_generator_paths["rigal_ic"]
# write MP Code text to file for RIGAL tools
try:
mp_filename = join(RIGAL_SCRATCH, "%s.mp" % self.schema_name)
with open(mp_filename, 'w') as f:
f.write(self.mp_code_text)
except Exception as e:
self.callback("Error writing temporary %s.mp file: %s"
% (self.schema_name, str(e)))
return
try:
# rc MP2-parser
_lines_1 = _run_rigal_now([rigal_rc, "MP2-parser"])
# rc schema
lines_2 = _run_rigal_now([rigal_ic, "MP2-parser", self.schema_name,
"tree", "1"])
except Exception as e:
self.callback("Error running the trace-generator: %s"%str(e))
return
# maybe return error
error_lines = list()
track_errors = False
for l in lines_2:
if l[:14] == "*** error: at ":
track_errors = True
if l[:18] == "Errors detected...":
track_errors = False
if track_errors:
error_lines.append(l.strip())
# done, return any error on one line
self.callback(" ".join(error_lines))
return
def mp_check_syntax(schema_name, mp_code_text, callback):
syntax_checker_thread = _SyntaxCheckerThread(
schema_name, mp_code_text, callback)
syntax_checker_thread.start()
......@@ -48,10 +48,10 @@ class LineNumberArea(QWidget):
self.mp_code_view = mp_code_view
def sizeHint(self):
return QSize(self.mp_code_view.lineNumberAreaWidth(), 0)
return QSize(self.mp_code_view.line_number_area_width(), 0)
def paintEvent(self, event):
self.mp_code_view.lineNumberAreaPaintEvent(event)
self.mp_code_view.line_number_area_paint_event(event)
class MPCodeView(QPlainTextEdit):
......@@ -75,8 +75,13 @@ class MPCodeView(QPlainTextEdit):
self.find_and_replace_dialog_wrapper \
= FindAndReplaceDialogWrapper(self)
# line number area
self.line_number_area = LineNumberArea(self)
# connect
mp_code_manager.signal_mp_code_loaded.connect(self._move_cursor_to_top)
mp_code_manager.signal_syntax_error_line_number_changed.connect(
self.line_number_area.update)
preferences_manager.signal_wrap_mode_changed.connect(self.set_wrap_mode)
preferences_manager.signal_use_auto_indent_changed.connect(
self.set_use_auto_indent)
......@@ -105,11 +110,10 @@ class MPCodeView(QPlainTextEdit):
# the word list model provides the list model for MP Code keywords
self.mp_code_string_list_model = QStringListModel()
self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
self.updateRequest.connect(self.updateLineNumberArea)
self.blockCountChanged.connect(self.update_line_number_area_width)
self.updateRequest.connect(self.update_line_number_area)
self.line_number_area = LineNumberArea(self)
self.updateLineNumberAreaWidth(0)
self.update_line_number_area_width(0)
self.set_wrap_mode(preferences_manager.wrap_mode())
self.set_use_auto_indent(preferences_manager.use_auto_indent())
self.set_use_dark_mode(preferences_manager.use_dark_mode())
......@@ -334,7 +338,7 @@ class MPCodeView(QPlainTextEdit):
super(MPCodeView, self).mousePressEvent(event)
self.mp_code_cursor_highlighter.highlight_selection()
def lineNumberAreaWidth(self):
def line_number_area_width(self):
digits = 1
count = max(1, self.blockCount())
while count >= 10:
......@@ -344,11 +348,11 @@ class MPCodeView(QPlainTextEdit):
return space
@pyqtSlot(int)
def updateLineNumberAreaWidth(self, _):
self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
def update_line_number_area_width(self, _):
self.setViewportMargins(self.line_number_area_width(), 0, 0, 0)
@pyqtSlot(QRect, int)
def updateLineNumberArea(self, rect, dy):
def update_line_number_area(self, rect, dy):
if dy:
self.line_number_area.scroll(0, dy)
......@@ -358,7 +362,7 @@ class MPCodeView(QPlainTextEdit):
rect.height())
if rect.contains(self.viewport().rect()):
self.updateLineNumberAreaWidth(0)
self.update_line_number_area_width(0)
def resizeEvent(self, event):
......@@ -366,10 +370,10 @@ class MPCodeView(QPlainTextEdit):
cr = self.contentsRect()
self.line_number_area.setGeometry(QRect(cr.left(), cr.top(),
self.lineNumberAreaWidth(),
self.line_number_area_width(),
cr.height()))
def lineNumberAreaPaintEvent(self, event):
def line_number_area_paint_event(self, event):
painter = QPainter(self.line_number_area)
# line number area background color based on using dark mode
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment