/* * 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; using MainWindow = SourceGen.WpfGui.MainWindow; namespace SourceGen { /// /// List of problems and oddities noted during analysis of the project. /// /// /// 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. /// public class MessageList : IEnumerable { /// /// One message entry. /// /// Instances are immutable. /// public class MessageEntry { public enum SeverityLevel { Unknown = 0, Info, Warning, Error } public SeverityLevel Severity { get; private set; } public int Offset { get; private set; } public enum MessageType { Unknown = 0, HiddenLabel, HiddenLocalVariableTable, HiddenVisualization, UnresolvedWeakRef, NonAddrLabelRef, InvalidOffsetOrLength, InvalidDescriptor, BankOverrun, } 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, LocalVariableTableIgnored, VisualizationIgnored, FormatDescriptorIgnored, } public ProblemResolution Resolution { get; private set; } public MessageEntry(SeverityLevel severity, int offset, MessageType mtype, object context, ProblemResolution resolution) { Debug.Assert(context != null); Severity = severity; Offset = offset; MsgType = mtype; Context = context; Resolution = resolution; } public override string ToString() { return Severity.ToString() + " +" + Offset.ToString("x6") + " " + MsgType + "(" + Context.ToString() + "): " + Resolution; } } /// /// Maximum file offset. Used to flag offsets as invalid. /// //public int MaxOffset { get; set; } /// /// List of messages. This is not kept in sorted order, because the DataGrid used to /// display it will do the sorting for us. Call the Sort() function to establish an /// initial sort. /// private List mList; /// /// Constructor. /// public MessageList() { mList = new List(); } // IEnumerable public IEnumerator 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(MessageEntry entry) { mList.Add(entry); } public void Clear() { mList.Clear(); } /// /// Sorts the list, by severity then offset. /// public void Sort() { mList.Sort(delegate (MessageEntry a, MessageEntry b) { if (a.Severity != b.Severity) { return (int)b.Severity - (int)a.Severity; } return a.Offset - b.Offset; }); } /// /// Formats a message for display. /// 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.HiddenLocalVariableTable: problem = Res.Strings.MSG_HIDDEN_LOCAL_VARIABLE_TABLE; break; case MessageEntry.MessageType.HiddenVisualization: problem = Res.Strings.MSG_HIDDEN_VISUALIZATION; break; case MessageEntry.MessageType.UnresolvedWeakRef: problem = Res.Strings.MSG_UNRESOLVED_WEAK_REF; break; case MessageEntry.MessageType.NonAddrLabelRef: problem = Res.Strings.MSG_NON_ADDR_LABEL_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; case MessageEntry.MessageType.BankOverrun: problem = Res.Strings.MSG_BANK_OVERRUN; 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.LocalVariableTableIgnored: resolution = Res.Strings.MSG_LOCAL_VARIABLE_TABLE_IGNORED; break; case MessageEntry.ProblemResolution.FormatDescriptorIgnored: resolution = Res.Strings.MSG_FORMAT_DESCRIPTOR_IGNORED; break; case MessageEntry.ProblemResolution.VisualizationIgnored: resolution = Res.Strings.MSG_VISUALIZATION_IGNORED; break; default: resolution = "???"; break; } return new MainWindow.MessageListItem(severity, entry.Offset, offset, problem, context, resolution); } public void DebugDump() { Debug.WriteLine("Message list (" + mList.Count + " entries):"); foreach (MessageEntry entry in mList) { Debug.WriteLine(entry); } } } }