1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-24 08:29:29 +00:00

Add message list, part 1

This converts the "problem list viewer" tool to a grid that appears
below the code list view when non-empty.  Not all messages are
problems, so it's being renamed to "message list".
This commit is contained in:
Andy McFadden 2019-10-20 14:40:32 -07:00
parent 3cc6f32c6f
commit 81dbab04ba
10 changed files with 346 additions and 410 deletions

View File

@ -168,8 +168,8 @@ 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; }
// List of messages, mostly problems detected during analysis.
public MessageList Messages { get; private set; }
#if DATA_PRESCAN
// Data scan results.
@ -233,7 +233,7 @@ namespace SourceGen {
PlatformSyms = new List<PlatformSymbols>();
ActiveDefSymbolList = new List<DefSymbol>();
Problems = new ProblemList();
Messages = new MessageList();
// Default to 65816. This will be replaced with value from project file or
// system definition.
@ -672,7 +672,7 @@ namespace SourceGen {
// to the user, and discarded.
//
// We do want to collect the failures so we can present them to the user.
Problems.Clear();
Messages.Clear();
Debug.Assert(reanalysisRequired != UndoableChange.ReanalysisScope.None);
reanalysisTimer.StartTask("DisasmProject.Analyze()");
@ -694,6 +694,8 @@ namespace SourceGen {
if (reanalysisRequired == UndoableChange.ReanalysisScope.CodeAndData) {
// Always want to start with a blank array. Going to be lazy and let the
// system allocator handle that for us.
// NOTE: don't generate any Messages during code analysis -- we clear the
// list at the start of each pass, and we don't always analyze code.
mAnattribs = new Anattrib[mFileData.Length];
reanalysisTimer.StartTask("CodeAnalysis.Analyze");
@ -863,12 +865,12 @@ namespace SourceGen {
if (offset < 0 || offset >= mFileData.Length) {
string msg = "invalid offset (desc=" + kvp.Value + ")";
genLog.LogE("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Error,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Error,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidOffsetOrLength,
MessageList.MessageEntry.MessageType.InvalidOffsetOrLength,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
Debug.Assert(false);
continue;
}
@ -878,12 +880,12 @@ namespace SourceGen {
string msg = "invalid offset+len: len=" + kvp.Value.Length +
" file=" + mFileData.Length;
genLog.LogE("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Error,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Error,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidOffsetOrLength,
MessageList.MessageEntry.MessageType.InvalidOffsetOrLength,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
Debug.Assert(false);
continue;
}
@ -891,12 +893,12 @@ namespace SourceGen {
if (!AddrMap.IsContiguous(offset, kvp.Value.Length)) {
string msg = "descriptor straddles address change; len=" + kvp.Value.Length;
genLog.LogE("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Error,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Error,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidOffsetOrLength,
MessageList.MessageEntry.MessageType.InvalidOffsetOrLength,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
continue;
}
@ -908,47 +910,47 @@ namespace SourceGen {
string msg = "unexpected length on instr format descriptor (" +
kvp.Value.Length + " vs " + mAnattribs[offset].Length + ")";
genLog.LogW("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Warning,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Warning,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidOffsetOrLength,
MessageList.MessageEntry.MessageType.InvalidOffsetOrLength,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
continue;
}
if (kvp.Value.Length == 1) {
// No operand to format!
string msg = "unexpected format descriptor on single-byte op";
genLog.LogW("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Warning,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Warning,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidDescriptor,
MessageList.MessageEntry.MessageType.InvalidDescriptor,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
continue;
}
if (!kvp.Value.IsValidForInstruction) {
string msg = "descriptor not valid for instruction: " + kvp.Value;
genLog.LogW("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Warning,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Warning,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidDescriptor,
MessageList.MessageEntry.MessageType.InvalidDescriptor,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
continue;
}
} else if (mAnattribs[offset].IsInstruction) {
// Mid-instruction format.
string msg = "unexpected mid-instruction format descriptor";
genLog.LogW("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Warning,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Warning,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidDescriptor,
MessageList.MessageEntry.MessageType.InvalidDescriptor,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
continue;
} else {
// Data or inline data. The data analyzer hasn't run yet. We want to
@ -969,12 +971,12 @@ namespace SourceGen {
string msg =
"data format descriptor overlaps code at +" + i.ToString("x6");
genLog.LogW("+" + offset.ToString("x6") + ": " + msg);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Warning,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Warning,
offset,
ProblemList.ProblemEntry.ProblemType.InvalidDescriptor,
MessageList.MessageEntry.MessageType.InvalidDescriptor,
msg,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
overlap = true;
break;
}
@ -1094,12 +1096,12 @@ namespace SourceGen {
Debug.WriteLine("Stripping hidden label '" + kvp.Value.Label + "'");
SymbolTable.Remove(kvp.Value);
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Warning,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Warning,
offset,
ProblemList.ProblemEntry.ProblemType.HiddenLabel,
MessageList.MessageEntry.MessageType.HiddenLabel,
kvp.Value.Label,
ProblemList.ProblemEntry.ProblemResolution.LabelIgnored));
MessageList.MessageEntry.ProblemResolution.LabelIgnored));
}
}
}
@ -1417,12 +1419,12 @@ namespace SourceGen {
}
} else {
// Reference to non-existent symbol.
Problems.Add(new ProblemList.ProblemEntry(
ProblemList.ProblemEntry.SeverityLevel.Info,
Messages.Add(new MessageList.MessageEntry(
MessageList.MessageEntry.SeverityLevel.Info,
offset,
ProblemList.ProblemEntry.ProblemType.UnresolvedWeakRef,
MessageList.MessageEntry.MessageType.UnresolvedWeakRef,
dfd.SymbolRef.Label,
ProblemList.ProblemEntry.ProblemResolution.FormatDescriptorIgnored));
MessageList.MessageEntry.ProblemResolution.FormatDescriptorIgnored));
}
} else if (dfd.FormatSubType == FormatDescriptor.SubType.Address) {
// not expecting this format on an instruction operand

View File

@ -74,8 +74,6 @@ 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; } }
@ -893,10 +891,6 @@ namespace SourceGen {
}
}
if (mShowProblemListDialog != null) {
mShowProblemListDialog.Update();
}
if (FormatDescriptor.DebugCreateCount != 0) {
Debug.WriteLine("FormatDescriptor total=" + FormatDescriptor.DebugCreateCount +
" prefab=" + FormatDescriptor.DebugPrefabCount + " (" +
@ -937,6 +931,10 @@ namespace SourceGen {
mReanalysisTimer.StartTask("Call DisasmProject.Analyze()");
mProject.Analyze(reanalysisRequired, mGenerationLog, mReanalysisTimer);
mReanalysisTimer.EndTask("Call DisasmProject.Analyze()");
mReanalysisTimer.StartTask("Update message list");
UpdateMessageList();
mReanalysisTimer.EndTask("Update message list");
}
mReanalysisTimer.StartTask("Generate DisplayList");
@ -944,6 +942,14 @@ namespace SourceGen {
mReanalysisTimer.EndTask("Generate DisplayList");
}
private void UpdateMessageList() {
List<MainWindow.MessageListItem> items = new List<MainWindow.MessageListItem>();
foreach (MessageList.MessageEntry entry in mProject.Messages) {
items.Add(MessageList.FormatMessage(entry, mOutputFormatter));
}
mMainWin.UpdateMessageList(items);
}
#endregion Project management
#region Main window UI event handlers
@ -1243,7 +1249,6 @@ namespace SourceGen {
mHexDumpDialog?.Close();
mShowAnalysisTimersDialog?.Close();
mShowAnalyzerOutputDialog?.Close();
mShowProblemListDialog?.Close();
mShowUndoRedoHistoryDialog?.Close();
while (mUnownedWindows.Count > 0) {
@ -1285,7 +1290,6 @@ namespace SourceGen {
mHexDumpDialog?.Close();
mShowAnalysisTimersDialog?.Close();
mShowAnalyzerOutputDialog?.Close();
mShowProblemListDialog?.Close();
mShowUndoRedoHistoryDialog?.Close();
// Discard all project state.
@ -3679,22 +3683,6 @@ 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,

View File

@ -18,21 +18,23 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using MainWindow = SourceGen.WpfGui.MainWindow;
namespace SourceGen {
/// <summary>
/// List of problems noted during analysis of the project.
/// List of problems and oddities 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> {
public class MessageList : IEnumerable<MessageList.MessageEntry> {
/// <summary>
/// One problem entry.
/// One message entry.
///
/// Instances are immutable.
/// </summary>
public class ProblemEntry {
public class MessageEntry {
public enum SeverityLevel {
Unknown = 0,
Info,
@ -43,62 +45,63 @@ namespace SourceGen {
public int Offset { get; private set; }
public enum ProblemType {
public enum MessageType {
Unknown = 0,
HiddenLabel,
UnresolvedWeakRef,
InvalidOffsetOrLength,
InvalidDescriptor,
}
public ProblemType Problem { get; private set; }
public MessageType MsgType { 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,
None,
LabelIgnored,
FormatDescriptorIgnored,
}
public ProblemResolution Resolution { get; private set; }
public ProblemEntry(SeverityLevel severity, int offset, ProblemType problem,
public MessageEntry(SeverityLevel severity, int offset, MessageType mtype,
object context, ProblemResolution resolution) {
Severity = severity;
Offset = offset;
Problem = problem;
MsgType = mtype;
Context = context;
Resolution = resolution;
}
public override string ToString() {
return Severity.ToString() + " +" + Offset.ToString("x6") + " " +
Problem + "(" + Context.ToString() + "): " + Resolution;
MsgType + "(" + Context.ToString() + "): " + Resolution;
}
}
/// <summary>
/// Maximum file offset. Used to flag offsets as invalid.
/// </summary>
public int MaxOffset { get; set; }
//public int MaxOffset { get; set; }
/// <summary>
/// List of problems. This is not kept in sorted order, because the DataGrid used to
/// List of messages. 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;
private List<MessageEntry> mList;
/// <summary>
/// Constructor.
/// </summary>
public ProblemList() {
mList = new List<ProblemEntry>();
public MessageList() {
mList = new List<MessageEntry>();
}
// IEnumerable
public IEnumerator<ProblemEntry> GetEnumerator() {
public IEnumerator<MessageEntry> GetEnumerator() {
// .Values is documented as O(1)
return mList.GetEnumerator();
}
@ -112,7 +115,7 @@ namespace SourceGen {
get { return mList.Count; }
}
public void Add(ProblemEntry entry) {
public void Add(MessageEntry entry) {
mList.Add(entry);
}
@ -120,9 +123,57 @@ namespace SourceGen {
mList.Clear();
}
/// <summary>
/// Formats a message for display.
/// </summary>
public static MainWindow.MessageListItem FormatMessage(MessageEntry entry,
Asm65.Formatter formatter) {
string severity = entry.Severity.ToString(); // enum
string offset = formatter.FormatOffset24(entry.Offset);
string problem;
switch (entry.MsgType) {
case MessageEntry.MessageType.HiddenLabel:
problem = Res.Strings.MSG_HIDDEN_LABEL;
break;
case MessageEntry.MessageType.UnresolvedWeakRef:
problem = Res.Strings.MSG_UNRESOLVED_WEAK_REF;
break;
case MessageEntry.MessageType.InvalidOffsetOrLength:
problem = Res.Strings.MSG_INVALID_OFFSET_OR_LENGTH;
break;
case MessageEntry.MessageType.InvalidDescriptor:
problem = Res.Strings.MSG_INVALID_DESCRIPTOR;
break;
default:
problem = "???";
break;
}
string context = entry.Context.ToString();
string resolution;
switch (entry.Resolution) {
case MessageEntry.ProblemResolution.None:
resolution = string.Empty;
break;
case MessageEntry.ProblemResolution.LabelIgnored:
resolution = Res.Strings.MSG_LABEL_IGNORED;
break;
case MessageEntry.ProblemResolution.FormatDescriptorIgnored:
resolution = Res.Strings.MSG_FORMAT_DESCRIPTOR_IGNORED;
break;
default:
resolution = "???";
break;
}
return new MainWindow.MessageListItem(severity, offset, problem, context, resolution);
}
public void DebugDump() {
Debug.WriteLine("Problem list (" + mList.Count + " entries):");
foreach (ProblemEntry entry in mList) {
Debug.WriteLine("Message list (" + mList.Count + " entries):");
foreach (MessageEntry entry in mList) {
Debug.WriteLine(entry);
}
}

View File

@ -106,6 +106,12 @@ limitations under the License.
<system:String x:Key="str_InvalidFormatWordSelUnevenFmt">Unable to format as word: each selected region must have an even number of bytes ({0} region(s) are selected).</system:String>
<system:String x:Key="str_LocalVariableTableClear">• Clear variables</system:String>
<system:String x:Key="str_LocalVariableTableEmpty">• Empty variable table</system:String>
<system:String x:Key="str_MsgFormatDescriptorIgnored">Format ignored</system:String>
<system:String x:Key="str_MsgHiddenLabel">Hidden label</system:String>
<system:String x:Key="str_MsgInvalidDescriptor">Invalid format desc</system:String>
<system:String x:Key="str_MsgInvalidOffsetOrLength">Invalid offset or len</system:String>
<system:String x:Key="str_MsgLabelIgnored">Label ignored</system:String>
<system:String x:Key="str_MsgUnresolvedWeakRef">Ref'd symbol not found</system:String>
<system:String x:Key="str_NoFilesAvailable">no files available</system:String>
<system:String x:Key="str_NoExportedSymbolsFound">No exported symbols found.</system:String>
<system:String x:Key="str_OpenDataDoesntExist">The file doesn't exist.</system:String>

View File

@ -193,6 +193,18 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_LocalVariableTableClear");
public static string LOCAL_VARIABLE_TABLE_EMPTY =
(string)Application.Current.FindResource("str_LocalVariableTableEmpty");
public static string MSG_FORMAT_DESCRIPTOR_IGNORED =
(string)Application.Current.FindResource("str_MsgFormatDescriptorIgnored");
public static string MSG_HIDDEN_LABEL =
(string)Application.Current.FindResource("str_MsgHiddenLabel");
public static string MSG_INVALID_DESCRIPTOR =
(string)Application.Current.FindResource("str_MsgInvalidDescriptor");
public static string MSG_INVALID_OFFSET_OR_LENGTH =
(string)Application.Current.FindResource("str_MsgInvalidOffsetOrLength");
public static string MSG_LABEL_IGNORED =
(string)Application.Current.FindResource("str_MsgLabelIgnored");
public static string MSG_UNRESOLVED_WEAK_REF =
(string)Application.Current.FindResource("str_MsgUnresolvedWeakRef");
public static string NO_FILES_AVAILABLE =
(string)Application.Current.FindResource("str_NoFilesAvailable");
public static string NO_EXPORTED_SYMBOLS_FOUND =

View File

@ -78,7 +78,7 @@
<Compile Include="Exporter.cs" />
<Compile Include="FormattedOperandCache.cs" />
<Compile Include="LocalVariableLookup.cs" />
<Compile Include="ProblemList.cs" />
<Compile Include="MessageList.cs" />
<Compile Include="Tests\GenTest.cs" />
<Compile Include="Tests\ProgressMessage.cs" />
<Compile Include="Tests\WpfGui\GenTestRunner.xaml.cs">
@ -88,9 +88,6 @@
<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>
@ -253,10 +250,6 @@
<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

@ -1,63 +0,0 @@
<!--
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_InvalidOffsetOrLength">Invalid offset or len</system:String>
<system:String x:Key="str_InvalidDescriptor">Invalid format desc</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

@ -1,133 +0,0 @@
/*
* 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;
case ProblemList.ProblemEntry.ProblemType.InvalidOffsetOrLength:
problem = (string)FindResource("str_InvalidOffsetOrLength");
break;
case ProblemList.ProblemEntry.ProblemType.InvalidDescriptor:
problem = (string)FindResource("str_InvalidDescriptor");
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

@ -20,6 +20,7 @@ limitations under the License.
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SourceGen.WpfGui"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="6502bench SourceGen"
Icon="/SourceGen;component/Res/SourceGenIcon.ico"
@ -169,7 +170,6 @@ 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"/>
@ -287,8 +287,6 @@ 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}"
@ -376,8 +374,6 @@ 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"
@ -511,6 +507,7 @@ limitations under the License.
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
</Grid>
<!-- Launch panel. Either this or the code list panel will be visible. -->
<Grid Name="launchPanel" Grid.Column="2"
Visibility="{Binding Path=LaunchPanelVisibility}" d:IsHidden="True">
<Grid.RowDefinitions>
@ -561,49 +558,95 @@ limitations under the License.
</StackPanel>
</Grid>
<ListView Name="codeListView" Grid.Column="2"
Style="{StaticResource codeListStyle}"
FontFamily="{StaticResource GeneralMonoFont}"
Visibility="{Binding Path=CodeListVisibility}"
VirtualizingStackPanel.VirtualizationMode="Recycling"
ItemContainerStyle="{StaticResource codeListItemStyle}"
SelectionChanged="CodeListView_SelectionChanged"
MouseDoubleClick="CodeListView_MouseDoubleClick">
<ListView.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<!-- <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text }" /> -->
</Style>
</ListView.Resources>
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Offset" Width="60"
DisplayMemberBinding="{Binding Offset}"/>
<GridViewColumn Header="Addr" Width="60"
CellTemplate="{StaticResource addrHighlightTemplate}"/>
<GridViewColumn Header="Bytes" Width="93"
DisplayMemberBinding="{Binding Bytes}"/>
<GridViewColumn Header="Flags" Width="80"
CellTemplate="{StaticResource flagsHighlightTemplate}"/>
<GridViewColumn Header="Attr" Width="54"
DisplayMemberBinding="{Binding Attr}"/>
<GridViewColumn Header="Label" Width="73"
CellTemplate="{StaticResource labelHighlightTemplate}"/>
<GridViewColumn Header="Opcode" Width="60"
DisplayMemberBinding="{Binding Opcode}"/>
<GridViewColumn Header="Operand" Width="100"
DisplayMemberBinding="{Binding Operand}"/>
<GridViewColumn Header="Comment" Width="344"
DisplayMemberBinding="{Binding Comment}"/>
</GridView>
</ListView.View>
<!-- Code list panel. Either this or the Launch panel will be visible. -->
<Grid Grid.Column="2" Name="codeListGrid" Visibility="{Binding Path=CodeListVisibility}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView.ContextMenu>
<!-- this is populated as a clone of the Actions menu during init -->
<ContextMenu/>
</ListView.ContextMenu>
<ListView Name="codeListView" Grid.Column="2"
Style="{StaticResource codeListStyle}"
FontFamily="{StaticResource GeneralMonoFont}"
VirtualizingStackPanel.VirtualizationMode="Recycling"
ItemContainerStyle="{StaticResource codeListItemStyle}"
SelectionChanged="CodeListView_SelectionChanged"
MouseDoubleClick="CodeListView_MouseDoubleClick">
<ListView.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<!-- <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text }" /> -->
</Style>
</ListView.Resources>
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Offset" Width="60"
DisplayMemberBinding="{Binding Offset}"/>
<GridViewColumn Header="Addr" Width="60"
CellTemplate="{StaticResource addrHighlightTemplate}"/>
<GridViewColumn Header="Bytes" Width="93"
DisplayMemberBinding="{Binding Bytes}"/>
<GridViewColumn Header="Flags" Width="80"
CellTemplate="{StaticResource flagsHighlightTemplate}"/>
<GridViewColumn Header="Attr" Width="54"
DisplayMemberBinding="{Binding Attr}"/>
<GridViewColumn Header="Label" Width="73"
CellTemplate="{StaticResource labelHighlightTemplate}"/>
<GridViewColumn Header="Opcode" Width="60"
DisplayMemberBinding="{Binding Opcode}"/>
<GridViewColumn Header="Operand" Width="100"
DisplayMemberBinding="{Binding Operand}"/>
<GridViewColumn Header="Comment" Width="344"
DisplayMemberBinding="{Binding Comment}"/>
</GridView>
</ListView.View>
</ListView>
<ListView.ContextMenu>
<!-- this is populated as a clone of the Actions menu during init -->
<ContextMenu/>
</ListView.ContextMenu>
</ListView>
<!-- A GridSplitter would be nice to make the height adjustable, but I had
trouble making everything disappear cleanly, particularly w.r.t. the splitter
working correctly after hide + re-show. See
https://stackoverflow.com/q/2502178/294248 for suggestions. -->
<!--<GridSplitter Name="messageLogSplitter" Grid.Row="1" Height="4"
HorizontalAlignment="Stretch" VerticalAlignment="Center"
Visibility="{Binding MessageListVisibility}"/>-->
<DockPanel Grid.Row="1" Visibility="{Binding MessageListVisibility}">
<Button DockPanel.Dock="Left" Content="Hide" Width="50" Margin="4,0,4,0"
VerticalAlignment="Bottom">
<Button.LayoutTransform>
<RotateTransform Angle="270"/>
</Button.LayoutTransform>
</Button>
<DataGrid DockPanel.Dock="Top" Name="messageGrid"
Height="100"
IsReadOnly="True"
ItemsSource="{Binding FormattedMessages}"
FontFamily="{StaticResource GeneralMonoFont}"
SnapsToDevicePixels="True"
GridLinesVisibility="Vertical"
VerticalGridLinesBrush="#FF7F7F7F"
AutoGenerateColumns="False"
HeadersVisibility="Column"
CanUserReorderColumns="False"
SelectionMode="Single"
VerticalScrollBarVisibility="Visible">
<!-- 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="160" Binding="{Binding Type}"/>
<DataGridTextColumn Header="Context" Width="380" Binding="{Binding Context}"/>
<DataGridTextColumn Header="Resolution" Width="250" Binding="{Binding Resolution}"/>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</Grid>
<Grid Name="rightPanel" Grid.Column="4">
<Grid.RowDefinitions>

View File

@ -84,69 +84,6 @@ namespace SourceGen.WpfGui {
}
bool mShowDebugMenu;
//
// Symbols list filter options.
//
public bool SymFilterUserLabels {
get { return mSymFilterUserLabels; }
set {
mSymFilterUserLabels = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_USER, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterUserLabels;
public bool SymFilterProjectSymbols {
get { return mSymFilterProjectSymbols; }
set {
mSymFilterProjectSymbols = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_PROJECT, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterProjectSymbols;
public bool SymFilterPlatformSymbols {
get { return mSymFilterPlatformSymbols; }
set {
mSymFilterPlatformSymbols = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_PLATFORM, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterPlatformSymbols;
public bool SymFilterAutoLabels {
get { return mSymFilterAutoLabels; }
set {
mSymFilterAutoLabels = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_AUTO, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterAutoLabels;
public bool SymFilterAddresses {
get { return mSymFilterAddresses; }
set {
mSymFilterAddresses = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_ADDR, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterAddresses;
public bool SymFilterConstants {
get { return mSymFilterConstants; }
set {
mSymFilterConstants = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_CONST, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterConstants;
/// <summary>
@ -330,9 +267,7 @@ namespace SourceGen.WpfGui {
/// Which panel are we showing, launchPanel or codeListView?
/// </summary>
public bool ShowCodeListView {
get {
return mShowCodeListView;
}
get { return mShowCodeListView; }
set {
mShowCodeListView = value;
OnPropertyChanged("LaunchPanelVisibility");
@ -1349,10 +1284,6 @@ 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();
@ -1459,7 +1390,6 @@ namespace SourceGen.WpfGui {
debugKeepAliveHackMenuItem.IsChecked = Sandbox.ScriptManager.UseKeepAliveHack;
debugAnalysisTimersMenuItem.IsChecked = mMainCtrl.IsDebugAnalysisTimersOpen;
debugAnalyzerOutputMenuItem.IsChecked = mMainCtrl.IsDebugAnalyzerOutputOpen;
debugProblemListMenuItem.IsChecked = mMainCtrl.IsDebugProblemListOpen;
debugUndoRedoHistoryMenuItem.IsChecked = mMainCtrl.IsDebugUndoRedoHistoryOpen;
}
@ -1506,7 +1436,6 @@ namespace SourceGen.WpfGui {
#endregion References panel
#region Notes panel
public class NotesListItem {
@ -1551,9 +1480,75 @@ namespace SourceGen.WpfGui {
#endregion Notes panel
#region Symbols panel
//
// Symbols list filter options.
//
public bool SymFilterUserLabels {
get { return mSymFilterUserLabels; }
set {
mSymFilterUserLabels = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_USER, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterUserLabels;
public bool SymFilterProjectSymbols {
get { return mSymFilterProjectSymbols; }
set {
mSymFilterProjectSymbols = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_PROJECT, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterProjectSymbols;
public bool SymFilterPlatformSymbols {
get { return mSymFilterPlatformSymbols; }
set {
mSymFilterPlatformSymbols = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_PLATFORM, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterPlatformSymbols;
public bool SymFilterAutoLabels {
get { return mSymFilterAutoLabels; }
set {
mSymFilterAutoLabels = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_AUTO, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterAutoLabels;
public bool SymFilterAddresses {
get { return mSymFilterAddresses; }
set {
mSymFilterAddresses = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_ADDR, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterAddresses;
public bool SymFilterConstants {
get { return mSymFilterConstants; }
set {
mSymFilterConstants = value;
AppSettings.Global.SetBool(AppSettings.SYMWIN_SHOW_CONST, value);
SymbolsListFilterChanged();
OnPropertyChanged();
}
}
private bool mSymFilterConstants;
/// <summary>
/// Symbols list DataGrid item.
/// </summary>
public class SymbolsListItem {
public Symbol Sym { get; private set; }
public string Type { get; private set; }
@ -1682,7 +1677,6 @@ namespace SourceGen.WpfGui {
#endregion Symbols panel
#region Info panel
/// <summary>
@ -1700,5 +1694,48 @@ namespace SourceGen.WpfGui {
private string mInfoBoxContents;
#endregion Info panel
#region Message list panel
public class MessageListItem {
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 MessageListItem(string severity, string offset, string type, string context,
string resolution) {
Severity = severity;
Offset = offset;
Type = type;
Context = context;
Resolution = resolution;
}
}
/// <summary>
/// ItemsSource for DataGrid.
/// </summary>
public ObservableCollection<MessageListItem> FormattedMessages { get; private set; } =
new ObservableCollection<MessageListItem>();
public void UpdateMessageList(List<MessageListItem> list) {
FormattedMessages.Clear();
foreach (MessageListItem item in list) {
FormattedMessages.Add(item);
}
OnPropertyChanged("MessageListVisibility");
}
public Visibility MessageListVisibility {
get {
bool visible = FormattedMessages.Count > 0;
return visible ? Visibility.Visible : Visibility.Collapsed;
}
}
#endregion Message list panel
}
}