diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-08-06 04:34:38 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-08-06 04:34:38 +0300 |
| commit | 255a47cf96e83e8d11befa9180dc4458f6767188 (patch) | |
| tree | 5b4229edce3c2c0bc56202e8711ce3a5949cb32f /Software/Visual_Studio | |
| parent | 03bc9bd370929884f98ee9488146646d44911efd (diff) | |
| download | Tango-255a47cf96e83e8d11befa9180dc4458f6767188.tar.gz Tango-255a47cf96e83e8d11befa9180dc4458f6767188.zip | |
Implemented interactive runtime error handling on procedures.
Diffstat (limited to 'Software/Visual_Studio')
7 files changed, 192 insertions, 12 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs index 5797d622a..fa8a4cab6 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs @@ -21,5 +21,8 @@ namespace Tango.FSE.Procedures.Contracts void ResetColrization(); void HighlightError(int position, int length); void ClearErrors(); + void ScrollToLine(int lineNumber); + void HighlightRuntimeError(int lineNumber); + void CloseRunTimeError(); } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs index ef5664772..88ab8dae9 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs @@ -87,7 +87,7 @@ namespace Tango.FSE.Procedures var stubType = MessageFactory.GetAvailableRequestStubs().SingleOrDefault(x => x.Name.ToLower() == messageName.ToLower() || x.Name.Replace("Request", "").ToLower() == messageName.ToLower()); if (stubType == null) { - throw new ArgumentException("Invalid stub '" + messageName + "'."); + throw new ArgumentException($"Stub '{messageName}' could not be located on the PMR."); } var stubProps = stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance); diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs index 68c8538b8..bd36350c1 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -200,6 +201,20 @@ namespace Tango.FSE.Procedures.ViewModels } } + private Exception _runtimeException; + public Exception RuntimeException + { + get { return _runtimeException; } + set { _runtimeException = value; RaisePropertyChangedAuto(); } + } + + private bool _runtimeErrorFree; + public bool RuntimeErrorFree + { + get { return _runtimeErrorFree; } + set { _runtimeErrorFree = value; RaisePropertyChangedAuto(); } + } + #endregion #region Commands @@ -244,6 +259,7 @@ namespace Tango.FSE.Procedures.ViewModels public RelayCommand<ProcedureResource> RemoveResourceCommand { get; set; } public RelayCommand<ProcedureResource> OpenResourceCommand { get; set; } public RelayCommand<ProcedureResource> ExportResourceCommand { get; set; } + public RelayCommand CloseRuntimeErrorCommand { get; set; } #endregion @@ -256,6 +272,7 @@ namespace Tango.FSE.Procedures.ViewModels FontSize = 13; ReplaceText = String.Empty; + RuntimeErrorFree = true; LoadedAssemblies = new ObservableCollection<Assembly>(); ResultsViewVM = new ResultsViewVM(); @@ -309,6 +326,7 @@ namespace Tango.FSE.Procedures.ViewModels RemoveResourceCommand = new RelayCommand<ProcedureResource>(RemoveProcedureResource); OpenResourceCommand = new RelayCommand<ProcedureResource>(OpenProcedureResource); ExportResourceCommand = new RelayCommand<ProcedureResource>(ExportProcedureResource); + CloseRuntimeErrorCommand = new RelayCommand(CloseRunTimeError); } #endregion @@ -557,6 +575,32 @@ namespace Tango.FSE.Procedures.ViewModels SelectedToolWindow = ToolWindows.Output; Logger.WriteLine("Project terminated with error:"); Logger.WriteLine(ex.FlattenMessage()); + + try + { + Regex regex = new Regex(@"OnExecute\(IProcedureContext context\) in :line (\d+)"); + var matches = regex.Matches(ex.ToString()).OfType<Match>().ToList(); + + if (matches.Count > 0) + { + var match = matches.First(); + + if (match.Groups.Count > 1) + { + var line = match.Groups[1].Value; + int lineNumber = int.Parse(line) - Project.Scripts.Count + 1; + OpenScript(Project.Scripts.FirstOrDefault(x => x.IsEntryPoint)); + RuntimeException = ex; + View.HighlightRuntimeError(lineNumber); + RuntimeErrorFree = false; + Mouse.OverrideCursor = null; + } + } + } + catch (Exception exx) + { + LogManager.Log(exx, "Error occurred while trying to show procedue runtime error."); + } } } @@ -1288,5 +1332,15 @@ namespace Tango.FSE.Procedures.ViewModels } #endregion + + #region Runtime Error + + private void CloseRunTimeError() + { + View.CloseRunTimeError(); + RuntimeErrorFree = true; + } + + #endregion } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml index 82f799d7b..dd442348f 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml @@ -36,7 +36,7 @@ <Grid> <Grid> <DockPanel> - <Menu IsMainMenu="True" DockPanel.Dock="Top"> + <Menu IsMainMenu="True" DockPanel.Dock="Top" IsHitTestVisible="{Binding RuntimeErrorFree}"> <MenuItem Header="_File"> <MenuItem Header="_New" MinWidth="250" Command="{Binding NewProjectCommand}" InputGestureText="Ctrl+N"> <MenuItem.Icon> @@ -166,7 +166,7 @@ </MenuItem> </Menu> - <Grid DockPanel.Dock="Top"> + <Grid DockPanel.Dock="Top" IsHitTestVisible="{Binding RuntimeErrorFree}"> <!--Toolbar--> <ToolBar ClipToBounds="False" Background="Transparent" HorizontalAlignment="Center" ToolBarTray.IsLocked="True"> <Button ToolTip="Save" Command="{Binding SaveProjectCommand}"> @@ -206,7 +206,7 @@ </ToolBar> </Grid> - <Grid DockPanel.Dock="Bottom" Height="25" Background="#007BA5" TextElement.FontSize="{StaticResource FSE_SmallFontSize}"> + <Grid DockPanel.Dock="Bottom" Height="25" Background="#007BA5" TextElement.FontSize="{StaticResource FSE_SmallFontSize}" IsHitTestVisible="{Binding RuntimeErrorFree}"> <!--Status Bar--> <Grid> <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Margin="5 0 0 0"> @@ -231,7 +231,7 @@ <ColumnDefinition MaxWidth="500" MinWidth="250" Width="134*"/> </Grid.ColumnDefinitions> - <Grid Width="350" Margin="0 33 0 0" Visibility="{Binding IsPublishPanelOpened,Converter={StaticResource BooleanToVisibilityConverter}}"> + <Grid IsHitTestVisible="{Binding RuntimeErrorFree}" Width="350" Margin="0 33 0 0" Visibility="{Binding IsPublishPanelOpened,Converter={StaticResource BooleanToVisibilityConverter}}"> <Border BorderThickness="0 0 5 0" BorderBrush="{StaticResource FSE_PrimaryBackgroundBrush}"> <DockPanel Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> <Border DockPanel.Dock="Top" Padding="5" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" BorderThickness="0 1 0 0" BorderBrush="{StaticResource FSE_BorderBrush}"> @@ -304,7 +304,7 @@ <RowDefinition MinHeight="30" Height="210*"/> </Grid.RowDefinitions> - <Grid Grid.Column="2"> + <Grid Grid.Column="2" IsHitTestVisible="{Binding RuntimeErrorFree}"> <!--Code Editor--> <DockPanel> <Grid DockPanel.Dock="Top" Height="35"> @@ -492,13 +492,14 @@ </Border> </Border> </Grid> + </Grid> </DockPanel> </Grid> - <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> + <GridSplitter IsHitTestVisible="{Binding RuntimeErrorFree}" Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> - <Grid Grid.Row="2"> + <Grid Grid.Row="2" IsHitTestVisible="{Binding RuntimeErrorFree}"> <!--Output & Error Tabs--> <TabControl SelectedIndex="{Binding SelectedToolWindow,Mode=TwoWay,Converter={StaticResource EnumToIntConverter}}" ItemContainerStyle="{StaticResource FSE_TabItem_VisualStudio_Output}" TabStripPlacement="Bottom" Margin="0" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderThickness="0"> <TabItem Header="OUTPUT"> @@ -630,7 +631,7 @@ </Button> <controls:FSERoundedCornersComboBox Height="25" FontSize="{StaticResource FSE_SmallFontSize}" ItemsSource="{Binding SelectionInputs}" SelectedValue="{Binding Value}" SelectedValuePath="Value" DisplayMemberPath="Name"/> </DockPanel> - </StackPanel> + </StackPanel> </DataTemplate> </Setter.Value> </Setter> @@ -734,11 +735,52 @@ </TabItem> </TabControl> </Grid> + + <Canvas Grid.Column="1" Grid.RowSpan="4" Background="Transparent" Margin="75 35 0 0" x:Name="runTimeErrorCanvas" IsHitTestVisible="True" Visibility="Hidden"> + <DockPanel x:Name="runTimeErrorDock" Canvas.Top="200" Canvas.Left="0"> + <Grid x:Name="runTimeErrorLineGrid" DockPanel.Dock="Bottom" Width="50" Height="50" HorizontalAlignment="Left"> + <Line RenderTransformOrigin="0.5,0.5" x:Name="runTimeErrorLine" X1="0" Y1="50" X2="50" Y2="0" Stroke="{StaticResource FSE_ErrorBrush}"> + <Line.RenderTransform> + <RotateTransform Angle="0" x:Name="runTimeErrorLineTransform" /> + </Line.RenderTransform> + </Line> + </Grid> + <Border Margin="50 0 0 0" Width="500" Height="250" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" Background="{StaticResource FSE_PrimaryBackgroundMidBrush}"> + <DockPanel> + <DockPanel DockPanel.Dock="Top" Height="25" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}"> + <controls:IconButton Width="20" Height="20" Cursor="Hand" ToolTip="Close" Padding="0" Icon="Close" DockPanel.Dock="Right" Margin="0 0 5 0" Command="{Binding CloseRuntimeErrorCommand}" /> + <material:PackIcon Margin="5 0 0 0" Kind="AlertOctagon" VerticalAlignment="Center" /> + <TextBlock Margin="5 2 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_SmallFontSize}">Runtime Error</TextBlock> + </DockPanel> + <Grid> + <DockPanel> + <TextBlock Margin="10" DockPanel.Dock="Top" Text="{Binding RuntimeException.Message,Mode=OneWay}" TextWrapping="Wrap" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_ErrorBrush}"></TextBlock> + <TextBox Style="{x:Null}" Margin="5 10 10 10" + HorizontalScrollBarVisibility="Hidden" + VerticalScrollBarVisibility="Auto" + AcceptsReturn="True" + TextWrapping="NoWrap" + BorderThickness="0" + Padding="5" + BorderBrush="{StaticResource FSE_BorderBrush}" + Background="Transparent" + Foreground="{StaticResource FSE_GrayBrush}" + CaretBrush="{StaticResource FSE_PrimaryForegroundBrush}" + FontSize="{StaticResource FSE_SmallFontSize}" Text="{Binding RuntimeException,Mode=OneWay}" + IsReadOnly="True"> + + </TextBox> + </DockPanel> + </Grid> + </DockPanel> + </Border> + </DockPanel> + </Canvas> </Grid> <GridSplitter Grid.Column="2" Width="5" HorizontalAlignment="Center" VerticalAlignment="Stretch" Margin="0 33 0 30" /> - <Grid Grid.Column="3"> + <Grid Grid.Column="3" IsHitTestVisible="{Binding RuntimeErrorFree}"> <Grid Margin="0 33 0 29"> <!--Project Explorer--> <DockPanel Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs index 1e5deb04a..a85508b24 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs @@ -16,6 +16,7 @@ using Tango.FSE.Procedures.Contracts; using Tango.FSE.Procedures.ViewModels; using Tango.Scripting.Basic; using Tango.Scripting.Editors; +using Tango.SharedUI.Helpers; namespace Tango.FSE.Procedures.Views { @@ -92,7 +93,7 @@ namespace Tango.FSE.Procedures.Views if (editor != null) { - int count = editor.ReplaceAll(text, replace); + int count = editor.ReplaceAll(text, replace); ColorizeKeyword(text); return count; } @@ -137,5 +138,49 @@ namespace Tango.FSE.Procedures.Views { GetAllEditors().ForEach(x => x.ClearErrors()); } + + public void ScrollToLine(int lineNumber) + { + GetCurrentEditor().ScrollToLine(lineNumber); + } + + public void HighlightRuntimeError(int lineNumber) + { + ScrollToLine(lineNumber); + var editor = GetCurrentEditor(); + editor.HighlightErrorLine(lineNumber); + UIHelper.DoEvents(); + Point? p = editor.GetLineVisualPosition(lineNumber); + + if (p != null) + { + Point point = p.Value; + point = new Point(point.X, point.Y - editor.VerticalOffset); + double height = editor.ActualHeight; + + if (point.Y > runTimeErrorDock.ActualHeight) + { + DockPanel.SetDock(runTimeErrorLineGrid, Dock.Bottom); + runTimeErrorLineTransform.Angle = 0; + Canvas.SetTop(runTimeErrorDock, point.Y - runTimeErrorDock.ActualHeight); + } + else + { + DockPanel.SetDock(runTimeErrorLineGrid, Dock.Top); + runTimeErrorLineTransform.Angle = 90; + Canvas.SetTop(runTimeErrorDock, point.Y); + } + + Canvas.SetLeft(runTimeErrorDock, Math.Min(point.X, editor.ActualWidth - 110 - runTimeErrorDock.ActualWidth)); + + runTimeErrorCanvas.Visibility = Visibility.Visible; + } + } + + public void CloseRunTimeError() + { + runTimeErrorCanvas.Visibility = Visibility.Hidden; + GetCurrentEditor().ResetColorizationByKeyword(); + } } } diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs index 8ca64ca18..2a1a7b7fc 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs @@ -121,9 +121,10 @@ namespace Tango.Scripting.Basic } } - var scriptOptions = ScriptOptions.Default.WithReferences(LoadReferenceAssemblies()); + var scriptOptions = ScriptOptions.Default.WithReferences(LoadReferenceAssemblies()).WithEmitDebugInformation(true); var s = CSharpScript.Create<object>(mainScriptCode, scriptOptions, typeof(GlobalObject<T>)); + result.Script = s; var compileResults = s.Compile(); diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs index 0802cf456..c650ad425 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs @@ -191,6 +191,14 @@ namespace Tango.Scripting.Editors public static readonly DependencyProperty ColorizeBrushProperty = DependencyProperty.Register("ColorizeBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.YellowGreen) { Opacity = 0.5 })); + public Brush ErrorLineBrush + { + get { return (Brush)GetValue(ErrorLineBrushProperty); } + set { SetValue(ErrorLineBrushProperty, value); } + } + public static readonly DependencyProperty ErrorLineBrushProperty = + DependencyProperty.Register("ErrorLineBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.Red) { Opacity = 0.5 })); + #endregion #region Constructors @@ -2486,6 +2494,33 @@ namespace Tango.Scripting.Editors errorMarkerService.RemoveAll(m => true); } + public void HighlightErrorLine(int lineNumber) + { + Document.BeginUpdate(); + + var line = Document.GetLineByNumber(lineNumber); + OffsetColorizer errorLineColrizer = new OffsetColorizer(line, line.Offset, line.EndOffset, ErrorLineBrush); + TextArea.TextView.LineTransformers.Add(errorLineColrizer); + + Document.EndUpdate(); + } + + public Point? GetLineVisualPosition(int lineNumber) + { + double top = TextArea.TextView.GetVisualTopByDocumentLine(lineNumber); + var visualLine = TextArea.TextView.GetVisualLine(lineNumber); + + if (visualLine != null) + { + var textLine = visualLine.GetTextLine(0); + var x = visualLine.GetTextLineVisualXPosition(textLine, visualLine.VisualLengthWithEndOfLineMarker); + var left = visualLine.VisualLengthWithEndOfLineMarker; + return new Point(x, top); + } + + return null; + } + #endregion } } |
