| File: Compiler\Logging\MessageOrigin.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using Internal.IL; using Internal.TypeSystem; #nullable enable namespace ILCompiler.Logging { public struct MessageOrigin : #if false IComparable<MessageOrigin>, #endif IEquatable<MessageOrigin> { public string? FileName { get; } public TypeSystemEntity? MemberDefinition { get; } public int? SourceLine { get; } public int? SourceColumn { get; } public int? ILOffset { get; } private const int HiddenLineNumber = 0xfeefee; public MessageOrigin(string fileName, int? sourceLine = null, int? sourceColumn = null) { FileName = fileName; SourceLine = sourceLine; SourceColumn = sourceColumn; MemberDefinition = null; ILOffset = null; } public MessageOrigin(TypeSystemEntity memberDefinition, string? fileName = null, int? sourceLine = 0, int? sourceColumn = 0) { FileName = fileName; MemberDefinition = memberDefinition; SourceLine = sourceLine; SourceColumn = sourceColumn; ILOffset = null; } // The assembly parameter should be specified if available as it allows assigning the diagnostic // to a an assembly (we group based on assembly). public MessageOrigin(string fileName, int sourceLine, int sourceColumn, ModuleDesc? assembly) { FileName = fileName; SourceLine = sourceLine; SourceColumn = sourceColumn; MemberDefinition = assembly; ILOffset = null; } public MessageOrigin(MethodIL methodBody, int ilOffset) { ILSequencePoint? correspondingSequencePoint = null; IEnumerable<ILSequencePoint>? sequencePoints = methodBody.GetDebugInfo()?.GetSequencePoints(); if (sequencePoints != null) { foreach (var sequencePoint in sequencePoints) { if (sequencePoint.Offset <= ilOffset) { correspondingSequencePoint = sequencePoint; } } // If the warning comes from hidden line (compiler generated code typically) // search for any sequence point with non-hidden line number and report that as a best effort. if (correspondingSequencePoint?.LineNumber == HiddenLineNumber) { // Reset the information as we don't want to use any of the info in the hidden sequence point correspondingSequencePoint = null; foreach (var sequencePoint in sequencePoints) { if (sequencePoint.LineNumber != HiddenLineNumber) { correspondingSequencePoint = sequencePoint; break; } } } } FileName = correspondingSequencePoint?.Document; MemberDefinition = methodBody.OwningMethod; SourceLine = correspondingSequencePoint?.LineNumber; SourceColumn = null; ILOffset = ilOffset; } public MessageOrigin WithInstructionOffset(MethodIL methodBody, int ilOffset) { Debug.Assert(methodBody.OwningMethod == MemberDefinition); return new MessageOrigin(methodBody, ilOffset); } public override string? ToString() { if (FileName == null) return null; StringBuilder sb = new StringBuilder(FileName); if (SourceLine.HasValue) { sb.Append('(').Append(SourceLine); if (SourceColumn.HasValue) sb.Append(',').Append(SourceColumn); sb.Append(')'); } return sb.ToString(); } public bool Equals(MessageOrigin other) => (FileName, MemberDefinition, SourceLine, SourceColumn, ILOffset) == (other.FileName, other.MemberDefinition, other.SourceLine, other.SourceColumn, other.ILOffset); public override bool Equals(object? obj) => obj is MessageOrigin messageOrigin && Equals(messageOrigin); public override int GetHashCode() => (FileName, MemberDefinition, SourceLine, SourceColumn, ILOffset).GetHashCode(); public static bool operator ==(MessageOrigin lhs, MessageOrigin rhs) => lhs.Equals(rhs); public static bool operator !=(MessageOrigin lhs, MessageOrigin rhs) => !lhs.Equals(rhs); #if false public int CompareTo(MessageOrigin other) { if (MemberDefinition != null && other.MemberDefinition != null) { var thisMember = Provider as IMemberDefinition; var otherMember = other.Provider as IMemberDefinition; TypeDefinition? thisTypeDef = (Provider as TypeDefinition) ?? (Provider as IMemberDefinition)?.DeclaringType; TypeDefinition? otherTypeDef = (other.Provider as TypeDefinition) ?? (other.Provider as IMemberDefinition)?.DeclaringType; var thisAssembly = thisTypeDef?.Module.Assembly ?? Provider as AssemblyDefinition; var otherAssembly = otherTypeDef?.Module.Assembly ?? other.Provider as AssemblyDefinition; int result = (thisAssembly?.Name.Name, thisTypeDef?.Name, thisMember?.Name).CompareTo ((otherAssembly?.Name.Name, otherTypeDef?.Name, otherMember?.Name)); if (result != 0) return result; if (ILOffset != null && other.ILOffset != null) return ILOffset.Value.CompareTo(other.ILOffset); return ILOffset == null ? (other.ILOffset == null ? 0 : 1) : -1; } else if (Provider == null && other.Provider == null) { if (FileName != null && other.FileName != null) { return string.Compare(FileName, other.FileName); } else if (FileName == null && other.FileName == null) { return (SourceLine, SourceColumn).CompareTo((other.SourceLine, other.SourceColumn)); } return (FileName == null) ? 1 : -1; } return (Provider == null) ? 1 : -1; } #endif } }