1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Linq;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Mono.Linker
{
public readonly struct MessageOrigin : IComparable<MessageOrigin>, IEquatable<MessageOrigin>
{
#nullable enable
public string? FileName { get; }
public IMemberDefinition? MemberDefinition { get; }
#nullable disable
public int SourceLine { get; }
public int SourceColumn { get; }
public int? ILOffset { get; }
const int HiddenLineNumber = 0xfeefee;
public MessageOrigin (IMemberDefinition memberDefinition)
: this (memberDefinition, null)
{
}
public MessageOrigin (string fileName, int sourceLine = 0, int sourceColumn = 0)
{
FileName = fileName;
SourceLine = sourceLine;
SourceColumn = sourceColumn;
MemberDefinition = null;
ILOffset = null;
}
public MessageOrigin (IMemberDefinition memberDefinition, int? ilOffset)
{
FileName = null;
MemberDefinition = memberDefinition;
SourceLine = 0;
SourceColumn = 0;
ILOffset = ilOffset;
}
public override string ToString ()
{
int sourceLine = SourceLine, sourceColumn = SourceColumn;
string fileName = FileName;
if (MemberDefinition is MethodDefinition method &&
method.DebugInformation.HasSequencePoints) {
var offset = ILOffset ?? 0;
SequencePoint correspondingSequencePoint = method.DebugInformation.SequencePoints
.Where (s => s.Offset <= offset)?.Last ();
// 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.StartLine == HiddenLineNumber) {
correspondingSequencePoint = method.DebugInformation.SequencePoints
.Where (s => s.StartLine != HiddenLineNumber)?.FirstOrDefault ();
}
if (correspondingSequencePoint != null) {
fileName = correspondingSequencePoint.Document.Url;
sourceLine = correspondingSequencePoint.StartLine;
sourceColumn = correspondingSequencePoint.StartColumn;
}
}
if (fileName == null)
return null;
StringBuilder sb = new StringBuilder (fileName);
if (sourceLine != 0) {
sb.Append ("(").Append (sourceLine);
if (sourceColumn != 0)
sb.Append (",").Append (sourceColumn);
sb.Append (")");
}
return sb.ToString ();
}
public bool Equals (MessageOrigin other) =>
(FileName, MemberDefinition, SourceLine, SourceColumn) == (other.FileName, other.MemberDefinition, other.SourceLine, other.SourceColumn);
public override bool Equals (object obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin);
public override int GetHashCode () => (FileName, MemberDefinition, SourceLine, SourceColumn).GetHashCode ();
public static bool operator == (MessageOrigin lhs, MessageOrigin rhs) => lhs.Equals (rhs);
public static bool operator != (MessageOrigin lhs, MessageOrigin rhs) => !lhs.Equals (rhs);
public int CompareTo (MessageOrigin other)
{
if (MemberDefinition != null && other.MemberDefinition != null) {
return (MemberDefinition.DeclaringType?.Module?.Assembly?.Name?.Name, MemberDefinition.DeclaringType?.Name, MemberDefinition?.Name).CompareTo
((other.MemberDefinition.DeclaringType?.Module?.Assembly?.Name?.Name, other.MemberDefinition.DeclaringType?.Name, other.MemberDefinition?.Name));
} else if (MemberDefinition == null && other.MemberDefinition == 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 (MemberDefinition == null) ? 1 : -1;
}
}
}
|