1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-05 09:28:56 +00:00

Add Problem List Viewer to debug menu

The analyzer sometimes runs into things that don't seem right, like
hidden labels or references to non-existent symbols, but has no way
to report them.  This adds a problem viewer.

I'm not quite ready to turn this into a real feature, so for now it's
a free-floating window accessed from the debug menu.

Also, updated some documentation.
This commit is contained in:
Andy McFadden 2019-09-21 13:38:16 -07:00
parent c05c42bf21
commit 41cd30a8c6
12 changed files with 426 additions and 31 deletions

View File

@ -168,6 +168,9 @@ namespace SourceGen {
// Project and platform symbols that are being referenced from code.
public List<DefSymbol> ActiveDefSymbolList { get; private set; }
// List of problems detected during analysis.
public ProblemList Problems { get; private set; }
#if DATA_PRESCAN
// Data scan results.
public TypedRangeSet RepeatedBytes { get; private set; }
@ -230,6 +233,8 @@ namespace SourceGen {
PlatformSyms = new List<PlatformSymbols>();
ActiveDefSymbolList = new List<DefSymbol>();
Problems = new ProblemList();
// Default to 65816. This will be replaced with value from project file or
// system definition.
ProjectProps.CpuType = CpuDef.CpuType.Cpu65816;
@ -645,6 +650,10 @@ namespace SourceGen {
// the program will never generate bad data, and any bad project file contents
// (possibly introduced by hand-editing) are identified at load time, called out
// to the user, and discarded.
//
// We do want to collect the failures so we can present them to the user.
Problems.Clear();
Debug.Assert(reanalysisRequired != UndoableChange.ReanalysisScope.None);
reanalysisTimer.StartTask("DisasmProject.Analyze()");
@ -773,6 +782,7 @@ namespace SourceGen {
//reanalysisTimer.DumpTimes("DisasmProject timers:", debugLog);
debugLog.LogI("Analysis complete");
Problems.DebugDump();
}
/// <summary>
@ -809,6 +819,7 @@ namespace SourceGen {
/// </summary>
/// <param name="genLog">Log for debug messages.</param>
private void ApplyFormatDescriptors(DebugLog genLog) {
// TODO: add these to ProblemList
foreach (KeyValuePair<int, FormatDescriptor> kvp in OperandFormats) {
int offset = kvp.Key;
@ -970,6 +981,13 @@ namespace SourceGen {
if (!mAnattribs[offset].IsStart) {
Debug.WriteLine("Stripping hidden label '" + kvp.Value.Label + "'");
SymbolTable.Remove(kvp.Value);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Warning,
offset,
ProblemList.ProblemEntry.ProblemType.HiddenLabel,
kvp.Value.Label,
ProblemList.ProblemEntry.ProblemResolution.LabelIgnored));
}
}
}
@ -1293,6 +1311,14 @@ namespace SourceGen {
Debug.WriteLine("NOTE: not xrefing +" + offset.ToString("x6") +
" " + sym);
}
} else {
// Reference to non-existent symbol.
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Info,
offset,
ProblemList.ProblemEntry.ProblemType.UnresolvedWeakRef,
dfd.SymbolRef.Label,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
}
} else if (dfd.FormatSubType == FormatDescriptor.SubType.Address) {
// not expecting this format on an instruction operand

View File

@ -74,6 +74,8 @@ namespace SourceGen {
public bool IsDebugAnalysisTimersOpen { get { return mShowAnalysisTimersDialog != null; } }
private Tools.WpfGui.ShowText mShowAnalyzerOutputDialog;
public bool IsDebugAnalyzerOutputOpen { get { return mShowAnalyzerOutputDialog != null; } }
private Tools.WpfGui.ProblemListViewer mShowProblemListDialog;
public bool IsDebugProblemListOpen { get { return mShowProblemListDialog != null; } }
private Tools.WpfGui.ShowText mShowUndoRedoHistoryDialog;
public bool IsDebugUndoRedoHistoryOpen { get { return mShowUndoRedoHistoryDialog != null; } }
@ -855,6 +857,10 @@ namespace SourceGen {
}
}
if (mShowProblemListDialog != null) {
mShowProblemListDialog.Update();
}
if (FormatDescriptor.DebugCreateCount != 0) {
Debug.WriteLine("FormatDescriptor total=" + FormatDescriptor.DebugCreateCount +
" prefab=" + FormatDescriptor.DebugPrefabCount + " (" +
@ -1201,6 +1207,7 @@ namespace SourceGen {
mHexDumpDialog?.Close();
mShowAnalysisTimersDialog?.Close();
mShowAnalyzerOutputDialog?.Close();
mShowProblemListDialog?.Close();
mShowUndoRedoHistoryDialog?.Close();
while (mUnownedWindows.Count > 0) {
@ -1242,6 +1249,7 @@ namespace SourceGen {
mHexDumpDialog?.Close();
mShowAnalysisTimersDialog?.Close();
mShowAnalyzerOutputDialog?.Close();
mShowProblemListDialog?.Close();
mShowUndoRedoHistoryDialog?.Close();
// Discard all project state.
@ -3531,6 +3539,22 @@ namespace SourceGen {
}
}
public void Debug_ShowProblemList() {
if (mShowProblemListDialog == null) {
Tools.WpfGui.ProblemListViewer dlg =
new Tools.WpfGui.ProblemListViewer(null, mProject, mOutputFormatter);
dlg.Closing += (sender, e) => {
Debug.WriteLine("Problem list window closed");
mShowProblemListDialog = null;
};
dlg.Show();
mShowProblemListDialog = dlg;
} else {
// Ask the dialog to close. Do the cleanup in the event.
mShowProblemListDialog.Close();
}
}
public void Debug_ShowUndoRedoHistory() {
if (mShowUndoRedoHistoryDialog == null) {
Tools.WpfGui.ShowText dlg = new Tools.WpfGui.ShowText(null,

128
SourceGen/ProblemList.cs Normal file
View File

@ -0,0 +1,128 @@
/*
* Copyright 2019 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace SourceGen {
/// <summary>
/// List of problems noted during analysis of the project.
/// </summary>
/// <remarks>
/// Could also make a place for load-time problems, though those tend to be resolved by
/// discarding the offending data, so not much value in continuing to report them.
/// </remarks>
public class ProblemList : IEnumerable<ProblemList.ProblemEntry> {
/// <summary>
/// One problem entry.
///
/// Instances are immutable.
/// </summary>
public class ProblemEntry {
public enum SeverityLevel {
Unknown = 0,
Info,
Warning,
Error
}
public SeverityLevel Severity { get; private set; }
public int Offset { get; private set; }
public enum ProblemType {
Unknown = 0,
HiddenLabel,
UnresolvedWeakRef,
}
public ProblemType Problem { get; private set; }
// Context object. Could be a label string, a format descriptor, etc.
public object Context { get; private set; }
public enum ProblemResolution {
Unknown = 0,
LabelIgnored,
FormatDescriptorIgnored,
}
public ProblemResolution Resolution { get; private set; }
public ProblemEntry(SeverityLevel severity, int offset, ProblemType problem,
object context, ProblemResolution resolution) {
Severity = severity;
Offset = offset;
Problem = problem;
Context = context;
Resolution = resolution;
}
public override string ToString() {
return Severity.ToString() + " +" + Offset.ToString("x6") + " " +
Problem + "(" + Context.ToString() + "): " + Resolution;
}
}
/// <summary>
/// Maximum file offset. Used to flag offsets as invalid.
/// </summary>
public int MaxOffset { get; set; }
/// <summary>
/// List of problems. This is not kept in sorted order, because the DataGrid used to
/// display it will do the sorting for us.
/// </summary>
private List<ProblemEntry> mList;
/// <summary>
/// Constructor.
/// </summary>
public ProblemList() {
mList = new List<ProblemEntry>();
}
// IEnumerable
public IEnumerator<ProblemEntry> GetEnumerator() {
// .Values is documented as O(1)
return mList.GetEnumerator();
}
// IEnumerable
IEnumerator IEnumerable.GetEnumerator() {
return mList.GetEnumerator();
}
public int Count {
get { return mList.Count; }
}
public void Add(ProblemEntry entry) {
mList.Add(entry);
}
public void Clear() {
mList.Clear();
}
public void DebugDump() {
Debug.WriteLine("Problem list:");
foreach (ProblemEntry entry in mList) {
Debug.WriteLine(entry);
}
}
}
}

View File

@ -229,6 +229,8 @@ not help you debug 6502 projects.</p>
<ul>
<li>Re-analyze (F5). Causes a full re-analysis. Useful if you think
the display is out of sync.</li>
<li>Show Problem List Viewer. Opens a floating window that shows some
of the problems encountered during the last analysis pass.</li>
<li>Show Undo/Redo History. Opens a floating window that lets you
watch the contents of the undo buffer while you work.</li>
<li>Show Analyzer Output. Opens a floating window with a text log from

View File

@ -33,27 +33,30 @@ This is explained in more detail <a href="#export-source">below</a>.
<li><a href="#merlin32">Merlin 32</a></li>
</ul>
<h3><a name="version">Version-Specific Code Generation</a></h3>
<p>Code generation must be tailored to the specific version of the
assembler. This is most easily understood with an example.</p>
<p>If you write <code>MVN $01,$02</code>, the assembler is expected to output
<code>54 02 01</code>, with the arguments reversed. cc65 v2.17 doesn't
do that; this is a bug that was fixed in a later version. So if you're
generating code for v2.17, you want to create source code with the
arguments the wrong way around.</p>
<p>Having version-dependent source code is a bad idea, so SourceGen
just outputs raw hex bytes for MVN/MVP instructions. This yields the
correct code for all versions of the assembler, but is ugly and
annoying. So we want to output actual MVN/MVP instructions when producing
code for newer versions of the assembler.</p>
<p>If the code has a statement like <code>MVN #$01,#$02</code>, the
assembler is expected to output <code>54 02 01</code>, with the arguments
reversed. cc65 v2.17 got it backward; the behavior was fixed in v2.18. The
bug means we can't generate the same <code>MVN</code>/<code>MVP</code>
instructions for both versions of the assembler.</p>
<p>Having version-dependent source code is a bad idea. If we generated
reversed operands (<code>MVN #$02,#$01</code>), we'd get the correct
output with v2.17, but the wrong output for v2.18. Unambiguous code can
be generated for all versions of the assembler by just outputting raw hex
bytes, but that's ugly and annoying, so we don't want to be stuck doing
that forever. We want to detect which version of the assembler is in
use, and output actual <code>MVN</code>/<code>MVP</code> instructions
when producing code for newer versions of the assembler.</p>
<p>When you configure a cross-assembler, SourceGen runs the executable with
version query args, and extracts the version information from the output
stream. This is used by the generator to ensure that the output will compile.
If no assembler is configured, SourceGen will produce code optimized
for the latest version of the assembler.</p>
<h2><a name="generate">Generating Source Code</a></h2>
<p>Cross assemblers tend to generate additional files, either compiler
@ -73,8 +76,8 @@ of a version number.</p>
<p>The Settings button will take you directly to the assembler configuration
tab in the application settings dialog.</p>
<p>Hit the Generate button to generate the source code into a file on disk.
The file will use the project name, with the ".dis65" replaced by
"_&lt;assembler&gt;.S".</p>
The file will use the project name, with the <code>.dis65</code> extension
replaced by <code>_&lt;assembler&gt;.S</code>.</p>
<p>The first 64KiB of each generated file will be shown in the preview
window. If multiple files were generated, you can use the "preview file"
drop-down to select between them. Line numbers are
@ -95,6 +98,15 @@ disabled from the
<a href="settings.html#app-settings">application settings</a>.</p>
<h3><a name="reserved-labels">Reserved Label Names</a></h3>
<p>Some label names aren't allowed. For example, 64tass reserves the
use of labels that begin with two underscores. Most assemblers will
also prevent you from using opcode mnemonics as labels (which means
you can't assemble <code>jmp jmp jmp</code>).</p>
<p>If a label doesn't appear to be legal, the generated code will have
a suitable replacement (e.g. <code>jmp_1 jmp jmp_1</code>).</p>
<h2><a name="assemble">Cross-Assembling Generated Code</a></h2>
<p>After generating sources, if you have a cross-assembler executable
@ -152,8 +164,8 @@ code, but also needs to know how to handle the corner cases.</p>
the load address. The <code>--nostart</code> flag is used to
suppress this.</li>
<li>By default, 64tass is case-insensitive, but SourceGen treats labels
as case-sensitive. The <code>--case-sensitive</code> must be passed to
the assembler.</li>
as case-sensitive. The <code>--case-sensitive</code> flag must be passed
to the assembler.</li>
<li>If you set the <code>--case-sensitive</code> flag, <b>all</b> opcodes
and operands must be lower-case. Most of the SourceGen options that
cause things to appear in upper case must be disabled.</li>
@ -172,15 +184,6 @@ code, but also needs to know how to handle the corner cases.</p>
an explicit character encoding definition must be provided.</li>
</ul>
<p>Notes:</p>
<ul>
<li>The "default text encoding" project property is used by SourceGen
to set the text encoding for the entire source file. For non-ASCII
projects, a small encoding table is generated at the top of the output.
This works for C64 PETSCII and C64 screen codes, but not for high
ASCII. This is done without passing "--ascii" on the command line.</li>
</ul>
<h3><a name="acme">ACME</a></h3>
@ -326,7 +329,7 @@ with links.</p>
<li><b>Include only selected lines</b>. This allows you to choose between
exporting all or part of a file. If no lines are selected, the entire
file will exported. This setting does <b>not</b> affect link generation
for HTML output, so you my have some dead internal links if you don't
for HTML output, so you may have some dead internal links if you don't
export the entire file.</li>
<li><b>Include notes</b>. Notes are normally excluded from generated
sources. Check this to include them.</li>

View File

@ -272,10 +272,18 @@ use the symbol. To make the difference clear, the lines in the references
window will either show "Sym" (to indicate that the symbol at the selected
line was referenced) or "Oth" (to indicate that some other symbol, or no
symbol, was used).</p>
<p>This is also relevant for project and platform symbols. If the
DATA0/1 labels were project symbols, the entry for <code>DATA1</code>
would not be included in the list of equates, because the symbol is
never used.</p>
<p>When an equate directive (generated for platform and project
symbols) or local variable assignment is selected, the References
window will show all references to that symbol. Unlike in-file
references, only the uses of that symbol are shown. So if you have
both a project symbol and a local variable for address $30, they
will show disjoint sets of references. Furthermore, if you explicitly
format an instruction operand as hex, e.g. <code>LDA $30</code>, it will
not appear in either set because it's not a symbolic reference.</p>
<p>The cross-reference data is used to generate the set of equate
directives at the top of the listing. If nothing references a platform
or project symbol, an equate directive will not be generated for it.</p>
<p>Double-clicking on a reference moves the code list selection to that
reference, and adds the previous selection to the navigation stack.</p>

View File

@ -79,6 +79,7 @@
<Compile Include="Exporter.cs" />
<Compile Include="FormattedOperandCache.cs" />
<Compile Include="LocalVariableLookup.cs" />
<Compile Include="ProblemList.cs" />
<Compile Include="Tests\GenTest.cs" />
<Compile Include="Tests\ProgressMessage.cs" />
<Compile Include="Tests\WpfGui\GenTestRunner.xaml.cs">
@ -88,6 +89,9 @@
<Compile Include="Tools\WpfGui\AsciiChart.xaml.cs">
<DependentUpon>AsciiChart.xaml</DependentUpon>
</Compile>
<Compile Include="Tools\WpfGui\ProblemListViewer.xaml.cs">
<DependentUpon>ProblemListViewer.xaml</DependentUpon>
</Compile>
<Compile Include="Tools\WpfGui\ShowText.xaml.cs">
<DependentUpon>ShowText.xaml</DependentUpon>
</Compile>
@ -242,6 +246,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Tools\WpfGui\ProblemListViewer.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Tools\WpfGui\ShowText.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -17,8 +17,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace SourceGen {
/// <summary>

View File

@ -0,0 +1,61 @@
<!--
Copyright 2019 faddenSoft
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Window x:Class="SourceGen.Tools.WpfGui.ProblemListViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SourceGen.Tools.WpfGui"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="Problems" ShowInTaskbar="True"
Height="500" Width="500" ResizeMode="CanResizeWithGrip"
Loaded="Window_Loaded">
<Window.Resources>
<system:String x:Key="str_HiddenLabel">Hidden label</system:String>
<system:String x:Key="str_UnresolvedWeakRef">Ref'd symbol not found</system:String>
<system:String x:Key="str_LabelIgnored">Label ignored</system:String>
<system:String x:Key="str_FormatDescriptorIgnored">Format ignored</system:String>
</Window.Resources>
<DockPanel Margin="8">
<TextBlock DockPanel.Dock="Top" Text="Problems detected during analysis:"/>
<DataGrid DockPanel.Dock="Bottom" Name="problemsGrid" Margin="0,4,0,0"
IsReadOnly="True"
ItemsSource="{Binding FormattedProblems}"
FontFamily="{StaticResource GeneralMonoFont}"
SnapsToDevicePixels="True"
GridLinesVisibility="Vertical"
VerticalGridLinesBrush="#FF7F7F7F"
AutoGenerateColumns="False"
HeadersVisibility="Column"
CanUserReorderColumns="False"
SelectionMode="Single">
<!-- should probably add ellipsis: https://stackoverflow.com/a/12880111/294248 -->
<DataGrid.Columns>
<DataGridTextColumn Header="Severity" Width="64" Binding="{Binding Severity}"/>
<DataGridTextColumn Header="Offset" Width="53" Binding="{Binding Offset}"/>
<DataGridTextColumn Header="Type" Width="119" Binding="{Binding Type}"/>
<DataGridTextColumn Header="Context" Width="119" Binding="{Binding Context}"/>
<DataGridTextColumn Header="Resolution" Width="119" Binding="{Binding Resolution}"/>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</Window>

View File

@ -0,0 +1,127 @@
/*
* Copyright 2019 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace SourceGen.Tools.WpfGui {
/// <summary>
/// Floating problem list window.
/// </summary>
public partial class ProblemListViewer : Window, INotifyPropertyChanged {
public class ProblemsListItem {
public string Severity { get; private set; }
public string Offset { get; private set; }
public string Type { get; private set; }
public string Context { get; private set; }
public string Resolution { get; private set; }
public ProblemsListItem(string severity, string offset, string type, string context,
string resolution) {
Severity = severity;
Offset = offset;
Type = type;
Context = context;
Resolution = resolution;
}
}
/// <summary>
/// Reference to project.
/// </summary>
private DisasmProject mProject;
/// <summary>
/// Text formatter.
/// </summary>
private Asm65.Formatter mFormatter;
/// <summary>
/// ItemsSource for DataGrid.
/// </summary>
public ObservableCollection<ProblemsListItem> FormattedProblems { get; private set; } =
new ObservableCollection<ProblemsListItem>();
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ProblemListViewer(Window owner, DisasmProject project, Asm65.Formatter formatter) {
InitializeComponent();
Owner = owner;
DataContext = this;
mProject = project;
mFormatter = formatter;
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
Update();
}
/// <summary>
/// Updates the contents of the DataGrid to the current values in mProject.Problems.
/// </summary>
public void Update() {
FormattedProblems.Clear();
foreach (ProblemList.ProblemEntry entry in mProject.Problems) {
ProblemsListItem newItem = FormatEntry(entry);
FormattedProblems.Add(newItem);
}
}
private ProblemsListItem FormatEntry(ProblemList.ProblemEntry entry) {
string severity = entry.Severity.ToString(); // enum
string offset = mFormatter.FormatOffset24(entry.Offset);
string problem;
switch (entry.Problem) {
case ProblemList.ProblemEntry.ProblemType.HiddenLabel:
problem = (string)FindResource("str_HiddenLabel");
break;
case ProblemList.ProblemEntry.ProblemType.UnresolvedWeakRef:
problem = (string)FindResource("str_UnresolvedWeakRef");
break;
default:
problem = "???";
break;
}
string context = entry.Context.ToString();
string resolution;
switch (entry.Resolution) {
case ProblemList.ProblemEntry.ProblemResolution.LabelIgnored:
resolution = (string)FindResource("str_LabelIgnored");
break;
case ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored:
resolution = (string)FindResource("str_FormatDescriptorIgnored");
break;
default:
resolution = "???";
break;
}
return new ProblemsListItem(severity, offset, problem, context, resolution);
}
}
}

View File

@ -164,6 +164,7 @@ limitations under the License.
<RoutedUICommand x:Key="Debug_ExtensionScriptInfoCmd" Text="Extension Script Info..."/>
<RoutedUICommand x:Key="Debug_ShowAnalysisTimersCmd" Text="Show Analysis Timers"/>
<RoutedUICommand x:Key="Debug_ShowAnalyzerOutputCmd" Text="Show Analyzer Output"/>
<RoutedUICommand x:Key="Debug_ShowProblemListCmd" Text="Show Problem List Viewer"/>
<RoutedUICommand x:Key="Debug_ShowUndoRedoHistoryCmd" Text="Show Undo/Redo History"/>
<RoutedUICommand x:Key="Debug_SourceGenerationTestsCmd" Text="Source Generation Tests..."/>
<RoutedUICommand x:Key="Debug_ToggleCommentRulersCmd" Text="Show Comment Rulers"/>
@ -279,6 +280,8 @@ limitations under the License.
CanExecute="IsProjectOpen" Executed="Debug_ShowAnalysisTimersCmd_Executed"/>
<CommandBinding Command="{StaticResource Debug_ShowAnalyzerOutputCmd}"
CanExecute="IsProjectOpen" Executed="Debug_ShowAnalyzerOutputCmd_Executed"/>
<CommandBinding Command="{StaticResource Debug_ShowProblemListCmd}"
CanExecute="IsProjectOpen" Executed="Debug_ShowProblemListCmd_Executed"/>
<CommandBinding Command="{StaticResource Debug_ShowUndoRedoHistoryCmd}"
CanExecute="IsProjectOpen" Executed="Debug_ShowUndoRedoHistoryCmd_Executed"/>
<CommandBinding Command="{StaticResource Debug_ToggleCommentRulersCmd}"
@ -361,6 +364,8 @@ limitations under the License.
<MenuItem Header="_DEBUG" Name="DebugMenu" SubmenuOpened="DebugMenu_SubmenuOpened"
Visibility="{Binding ShowDebugMenu, Converter={StaticResource BoolToVis}}">
<MenuItem Command="Refresh" Header="Re-analyze"/>
<MenuItem Name="debugProblemListMenuItem"
Command="{StaticResource Debug_ShowProblemListCmd}" IsCheckable="True"/>
<MenuItem Name ="debugUndoRedoHistoryMenuItem"
Command="{StaticResource Debug_ShowUndoRedoHistoryCmd}" IsCheckable="True"/>
<MenuItem Name="debugAnalyzerOutputMenuItem"

View File

@ -1278,6 +1278,10 @@ namespace SourceGen.WpfGui {
mMainCtrl.Debug_ShowAnalyzerOutput();
}
private void Debug_ShowProblemListCmd_Executed(object sender, ExecutedRoutedEventArgs e) {
mMainCtrl.Debug_ShowProblemList();
}
private void Debug_ShowUndoRedoHistoryCmd_Executed(object sender,
ExecutedRoutedEventArgs e) {
mMainCtrl.Debug_ShowUndoRedoHistory();
@ -1384,6 +1388,7 @@ namespace SourceGen.WpfGui {
debugKeepAliveHackMenuItem.IsChecked = Sandbox.ScriptManager.UseKeepAliveHack;
debugAnalysisTimersMenuItem.IsChecked = mMainCtrl.IsDebugAnalysisTimersOpen;
debugAnalyzerOutputMenuItem.IsChecked = mMainCtrl.IsDebugAnalyzerOutputOpen;
debugProblemListMenuItem.IsChecked = mMainCtrl.IsDebugProblemListOpen;
debugUndoRedoHistoryMenuItem.IsChecked = mMainCtrl.IsDebugUndoRedoHistoryOpen;
}