Commit 2361a814 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Advanced autocompletion

parent 16388f61
...@@ -24,6 +24,7 @@ __all__ = ['Input', 'Output', 'State', 'Task', 'ProcedureCall', 'Label', ...@@ -24,6 +24,7 @@ __all__ = ['Input', 'Output', 'State', 'Task', 'ProcedureCall', 'Label',
#import traceback #import traceback
import logging import logging
from itertools import chain
from PySide.QtCore import Qt, QPoint, QRect, QRectF from PySide.QtCore import Qt, QPoint, QRect, QRectF
from PySide.QtGui import(QPainterPath, QBrush, QColor, QRadialGradient, QPen) from PySide.QtGui import(QPainterPath, QBrush, QColor, QRadialGradient, QPen)
...@@ -56,6 +57,50 @@ SDL_REDBOLD = ['\\b{word}\\b'.format(word=word) for word in ( ...@@ -56,6 +57,50 @@ SDL_REDBOLD = ['\\b{word}\\b'.format(word=word) for word in (
'TASK', 'PROCESS', 'LABEL', 'JOIN', 'CONNECTION', 'CONNECT')] 'TASK', 'PROCESS', 'LABEL', 'JOIN', 'CONNECTION', 'CONNECT')]
def variables_autocompletion(symbol):
''' Intelligent autocompletion for variables - including struct fields '''
res = ()
if not symbol.text:
return res
parts = symbol.text.context.split('!')
if len(parts) == 0:
return res
elif len(parts) == 1:
# Return the list of variables
res = set(CONTEXT.variables.keys() + AST.asn1_constants.keys())
else:
var = parts[0].lower()
try:
var_t = ogParser.find_variable_type(var, CONTEXT)
basic = ogParser.find_basic_type(var_t, AST.dataview)
res = (field.replace('-', '_') for field in basic.Children.keys())
except (AttributeError, TypeError):
res = []
else:
for each in parts[1:-1]:
try:
for child, childtype in basic.Children.viewitems():
if child.lower() == each.lower().replace('_', '-'):
basic = ogParser.find_basic_type(childtype.type,
AST.dataview)
break
else:
res = ()
break
except (AttributeError, TypeError):
res = ()
break
else:
try:
res = (field.replace('-', '_')
for field in basic.Children.keys())
except AttributeError:
res = ()
return res
# pylint: disable=R0904 # pylint: disable=R0904
class Input(HorizontalSymbol): class Input(HorizontalSymbol):
''' SDL INPUT Symbol ''' ''' SDL INPUT Symbol '''
...@@ -63,7 +108,6 @@ class Input(HorizontalSymbol): ...@@ -63,7 +108,6 @@ class Input(HorizontalSymbol):
_insertable_followers = ['Task', 'ProcedureCall', 'Output', 'Decision', _insertable_followers = ['Task', 'ProcedureCall', 'Output', 'Decision',
'Input', 'Label', 'Connect'] 'Input', 'Label', 'Connect']
_terminal_followers = ['Join', 'State', 'ProcedureStop'] _terminal_followers = ['Join', 'State', 'ProcedureStop']
completion_list = set()
common_name = 'input_part' common_name = 'input_part'
# Define reserved keywords for the syntax highlighter # Define reserved keywords for the syntax highlighter
...@@ -108,6 +152,14 @@ class Input(HorizontalSymbol): ...@@ -108,6 +152,14 @@ class Input(HorizontalSymbol):
self.setPath(path) self.setPath(path)
super(Input, self).set_shape(width, height) super(Input, self).set_shape(width, height)
@property
def completion_list(self):
''' Set auto-completion list '''
if '(' in unicode(self):
return variables_autocompletion(self)
else:
return (sig['name'] for sig in CONTEXT.input_signals)
class Connect(Input): class Connect(Input):
''' Connect point below a nested state ''' ''' Connect point below a nested state '''
...@@ -145,7 +197,6 @@ class Output(VerticalSymbol): ...@@ -145,7 +197,6 @@ class Output(VerticalSymbol):
# Define reserved keywords for the syntax highlighter # Define reserved keywords for the syntax highlighter
blackbold = SDL_BLACKBOLD blackbold = SDL_BLACKBOLD
redbold = SDL_REDBOLD redbold = SDL_REDBOLD
completion_list = set()
def __init__(self, parent=None, ast=None): def __init__(self, parent=None, ast=None):
ast = ast or ogAST.Output() ast = ast or ogAST.Output()
...@@ -171,6 +222,12 @@ class Output(VerticalSymbol): ...@@ -171,6 +222,12 @@ class Output(VerticalSymbol):
self.setPath(path) self.setPath(path)
super(Output, self).set_shape(width, height) super(Output, self).set_shape(width, height)
@property
def completion_list(self):
''' Set auto-completion list '''
return chain(variables_autocompletion(self),
(sig['name'] for sig in CONTEXT.output_signals))
# pylint: disable=R0904 # pylint: disable=R0904
class Decision(VerticalSymbol): class Decision(VerticalSymbol):
...@@ -184,7 +241,7 @@ class Decision(VerticalSymbol): ...@@ -184,7 +241,7 @@ class Decision(VerticalSymbol):
blackbold = SDL_BLACKBOLD + ['\\b{}\\b'.format(word) blackbold = SDL_BLACKBOLD + ['\\b{}\\b'.format(word)
for word in ('AND', 'OR')] for word in ('AND', 'OR')]
redbold = SDL_REDBOLD redbold = SDL_REDBOLD
completion_list = {'length', 'present'} #completion_list = {'length', 'present'}
def __init__(self, parent=None, ast=None): def __init__(self, parent=None, ast=None):
ast = ast or ogAST.Decision() ast = ast or ogAST.Decision()
...@@ -211,6 +268,11 @@ class Decision(VerticalSymbol): ...@@ -211,6 +268,11 @@ class Decision(VerticalSymbol):
return False return False
return True return True
@property
def completion_list(self):
''' Set auto-completion list '''
return chain(variables_autocompletion(self), ('length', 'present'))
def branches(self): def branches(self):
''' Return the list of decision answers (as a generator) ''' ''' Return the list of decision answers (as a generator) '''
return (branch for branch in self.childSymbols() return (branch for branch in self.childSymbols()
...@@ -404,7 +466,6 @@ class ProcedureStop(Join): ...@@ -404,7 +466,6 @@ class ProcedureStop(Join):
ast.width = 35 ast.width = 35
ast.height = 35 ast.height = 35
super(ProcedureStop, self).__init__(parent, ast) super(ProcedureStop, self).__init__(parent, ast)
completion_list = set()
def set_shape(self, width, height): def set_shape(self, width, height):
''' Define the symbol shape ''' ''' Define the symbol shape '''
...@@ -423,6 +484,11 @@ class ProcedureStop(Join): ...@@ -423,6 +484,11 @@ class ProcedureStop(Join):
# call Join superclass, otherwise symbol will take Join shape # call Join superclass, otherwise symbol will take Join shape
super(Join, self).set_shape(circ, circ) super(Join, self).set_shape(circ, circ)
@property
def completion_list(self):
''' Set auto-completion list '''
return variables_autocompletion(self)
# pylint: disable=R0904 # pylint: disable=R0904
class Label(VerticalSymbol): class Label(VerticalSymbol):
...@@ -483,7 +549,6 @@ class Task(VerticalSymbol): ...@@ -483,7 +549,6 @@ class Task(VerticalSymbol):
# Define reserved keywords for the syntax highlighter # Define reserved keywords for the syntax highlighter
blackbold = SDL_BLACKBOLD blackbold = SDL_BLACKBOLD
redbold = SDL_REDBOLD redbold = SDL_REDBOLD
#completion_list = set()
def __init__(self, parent=None, ast=None): def __init__(self, parent=None, ast=None):
''' Initializes the TASK symbol ''' ''' Initializes the TASK symbol '''
...@@ -510,47 +575,9 @@ class Task(VerticalSymbol): ...@@ -510,47 +575,9 @@ class Task(VerticalSymbol):
@property @property
def completion_list(self): def completion_list(self):
''' Dynamically set completion list depending on current context ''' ''' Set auto-completion list '''
res = [] return chain(variables_autocompletion(self),
if not self.text: ogParser.SPECIAL_OPERATORS.viewkeys())
return res
#print self.text.context.encode('utf-8')
parts = self.text.context.split('!')
if len(parts) == 0:
return res
elif len(parts) == 1:
# Return the list of variables
res = set(CONTEXT.variables.keys() + AST.asn1_constants.keys())
else:
var = parts[0].lower()
try:
var_t = ogParser.find_variable_type(var, CONTEXT)
basic = ogParser.find_basic_type(var_t, AST.dataview)
res = (field.replace('-', '_')
for field in basic.Children.keys())
except (AttributeError, TypeError):
res = []
else:
for each in parts[1:-1]:
try:
for child, childtype in basic.Children.viewitems():
if child.lower() == each.lower().replace('_', '-'):
basic = ogParser.find_basic_type(childtype.type,
AST.dataview)
break
else:
res = []
break
except (AttributeError, TypeError):
res = []
break
else:
try:
res = (field.replace('-', '_')
for field in basic.Children.keys())
except AttributeError:
res = []
return res
# pylint: disable=R0904 # pylint: disable=R0904
...@@ -565,7 +592,7 @@ class ProcedureCall(VerticalSymbol): ...@@ -565,7 +592,7 @@ class ProcedureCall(VerticalSymbol):
blackbold = ['\\bWRITELN\\b', '\\bWRITE\\b', blackbold = ['\\bWRITELN\\b', '\\bWRITE\\b',
'\\bSET_TIMER\\b', '\\bRESET_TIMER\\b'] '\\bSET_TIMER\\b', '\\bRESET_TIMER\\b']
redbold = SDL_REDBOLD redbold = SDL_REDBOLD
completion_list = {'set_timer', 'reset_timer', 'write', 'writeln'} #completion_list = {'set_timer', 'reset_timer', 'write', 'writeln'}
def __init__(self, parent=None, ast=None): def __init__(self, parent=None, ast=None):
ast = ast or ogAST.Output(defName='') ast = ast or ogAST.Output(defName='')
...@@ -590,6 +617,13 @@ class ProcedureCall(VerticalSymbol): ...@@ -590,6 +617,13 @@ class ProcedureCall(VerticalSymbol):
self.setPath(path) self.setPath(path)
super(ProcedureCall, self).set_shape(width, height) super(ProcedureCall, self).set_shape(width, height)
@property
def completion_list(self):
''' Set auto-completion list '''
return chain((proc.inputString for proc in CONTEXT.procedures),
variables_autocompletion(self),
('set_timer', 'reset_timer', 'write', 'writeln'))
# pylint: disable=R0904 # pylint: disable=R0904
class TextSymbol(HorizontalSymbol): class TextSymbol(HorizontalSymbol):
...@@ -599,7 +633,7 @@ class TextSymbol(HorizontalSymbol): ...@@ -599,7 +633,7 @@ class TextSymbol(HorizontalSymbol):
# Define reserved keywords for the syntax highlighter # Define reserved keywords for the syntax highlighter
blackbold = SDL_BLACKBOLD blackbold = SDL_BLACKBOLD
redbold = SDL_REDBOLD redbold = SDL_REDBOLD
completion_list = set() #completion_list = set()
def __init__(self, ast=None): def __init__(self, ast=None):
''' Create a Text Symbol ''' ''' Create a Text Symbol '''
...@@ -623,6 +657,11 @@ class TextSymbol(HorizontalSymbol): ...@@ -623,6 +657,11 @@ class TextSymbol(HorizontalSymbol):
ast, _, _, _, _ = self.parser.parseSingleElement('text_area', pr_text) ast, _, _, _, _ = self.parser.parseSingleElement('text_area', pr_text)
#Task.completion_list |= {dcl for dcl in ast.variables.keys()} #Task.completion_list |= {dcl for dcl in ast.variables.keys()}
@property
def completion_list(self):
''' Set auto-completion list '''
return AST.dataview.viewkeys()
def set_shape(self, width, height): def set_shape(self, width, height):
''' Define the polygon of the text symbol ''' ''' Define the polygon of the text symbol '''
path = QPainterPath() path = QPainterPath()
...@@ -664,7 +703,6 @@ class State(VerticalSymbol): ...@@ -664,7 +703,6 @@ class State(VerticalSymbol):
# Define reserved keywords for the syntax highlighter # Define reserved keywords for the syntax highlighter
blackbold = SDL_BLACKBOLD blackbold = SDL_BLACKBOLD
redbold = SDL_REDBOLD redbold = SDL_REDBOLD
completion_list = set()
def __init__(self, parent=None, ast=None): def __init__(self, parent=None, ast=None):
ast = ast or ogAST.State() ast = ast or ogAST.State()
...@@ -720,8 +758,12 @@ class State(VerticalSymbol): ...@@ -720,8 +758,12 @@ class State(VerticalSymbol):
''' When text was entered, update state completion list ''' ''' When text was entered, update state completion list '''
# Get AST for the symbol # Get AST for the symbol
ast, _, _, _, _ = self.parser.parseSingleElement('state', pr_text) ast, _, _, _, _ = self.parser.parseSingleElement('state', pr_text)
State.completion_list |= set(ast.statelist) #State.completion_list |= set(ast.statelist)
@property
def completion_list(self):
''' Set auto-completion list '''
return (state for state in CONTEXT.mapping if state != 'START')
def set_shape(self, width, height): def set_shape(self, width, height):
''' Compute the polygon to fit in width, height ''' ''' Compute the polygon to fit in width, height '''
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment