Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
cd21f84c
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
cd21f84c
编写于
5月 20, 2016
作者:
N
Nick Guerrera
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #11390 from nguerrera/duplicate-rule-metadata
/errorlog improvements, fixes, and marking as v1.0.0
上级
a3a55077
e090e146
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
343 addition
and
88 deletion
+343
-88
docs/compilers/Error Log Format.md
docs/compilers/Error Log Format.md
+3
-28
src/Compilers/Core/CodeAnalysisTest/Diagnostics/ErrorLoggerTests.cs
...ers/Core/CodeAnalysisTest/Diagnostics/ErrorLoggerTests.cs
+231
-34
src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs
src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs
+5
-0
src/Compilers/Core/Portable/CommandLine/ErrorLogger.cs
src/Compilers/Core/Portable/CommandLine/ErrorLogger.cs
+98
-22
src/Test/Utilities/Shared/Diagnostics/DiagnosticExtensions.cs
...Test/Utilities/Shared/Diagnostics/DiagnosticExtensions.cs
+6
-4
未找到文件。
docs/compilers/Error Log Format.md
浏览文件 @
cd21f84c
Introduction
============
The C# and Visual Basic compilers support a /errorlog:
<file>
switch on
the command line to log all diagnostics in a structured, JSON format.
The log format is SARIF (Static Analysis Results Interchange Format)
and is defined by https://github.com/sarif-standard/sarif-spec
Note that the format has not been finalized and the specification is
still a draft. It will remain subject to breaking changes until the
`version`
property is emitted with a value of "1.0" or greater.
This document does not repeat the details of the SARIF format, but
rather adds information that is specific to the implementation provided
by the C# and Visual Basic Compilers.
Result Properties
================
The SARIF standard allows the
`properties`
property of
`result`
objects
to contain arbitrary (string, string) key-value pairs.
The keys and values used by the C# and VB compilers are serialized from
the corresponding
`Microsoft.CodeAnalysis.Diagnostic`
as follows:
Key | Value
------------------------ | ------------
"warningLevel" |
`Diagnostic.WarningLevel`
"category" |
`Diagnostic.Category`
"isEnabledByDefault" |
`Diagnostic.IsEnabledByDefault
"customProperties" | `
Diagnostic.Properties
`
The log format is SARIF (Static Analysis Results Interchange Format):
See https://sarifweb.azurewebsites.net/ for the format specification,
JSON schema, and other related resources.
\ No newline at end of file
src/Compilers/Core/CodeAnalysisTest/Diagnostics/ErrorLoggerTests.cs
浏览文件 @
cd21f84c
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using
Xunit
;
using
System.IO
;
using
System
;
using
System.Collections.Generic
;
using
System.Globalization
;
using
System.IO
;
using
System.Text
;
using
Microsoft.CodeAnalysis.CSharp
;
using
Microsoft.CodeAnalysis.Text
;
using
System.Collections.Generic
;
using
Xunit
;
namespace
Microsoft.CodeAnalysis.UnitTests.Diagnostics
{
...
...
@@ -18,27 +19,33 @@ public class ErrorLoggerTests
public
void
AdditionalLocationsAsRelatedLocations
()
{
var
stream
=
new
MemoryStream
();
using
(
var
logger
=
new
ErrorLogger
(
stream
,
"toolName"
,
"1.2.3.4"
,
new
Version
(
1
,
2
,
3
,
4
),
CultureInfo
.
InvariantCulture
))
using
(
var
logger
=
new
ErrorLogger
(
stream
,
"toolName"
,
"1.2.3.4"
,
new
Version
(
1
,
2
,
3
,
4
),
new
CultureInfo
(
"fr-CA"
)
))
{
var
mainLocation
=
Location
.
Create
(
@"Z:\MainLocation.cs"
,
new
TextSpan
(
0
,
0
),
new
LinePositionSpan
(
LinePosition
.
Zero
,
LinePosition
.
Zero
));
var
additionalLocation
=
Location
.
Create
(
@"Z:\AdditionalLocation.cs"
,
new
TextSpan
(
0
,
0
),
new
LinePositionSpan
(
LinePosition
.
Zero
,
LinePosition
.
Zero
));
var
span
=
new
TextSpan
(
0
,
0
);
var
position
=
new
LinePositionSpan
(
LinePosition
.
Zero
,
LinePosition
.
Zero
);
var
mainLocation
=
Location
.
Create
(
@"Z:\Main Location.cs"
,
span
,
position
);
var
descriptor
=
new
DiagnosticDescriptor
(
"TST"
,
"_TST_"
,
""
,
""
,
DiagnosticSeverity
.
Error
,
false
);
IEnumerable
<
Location
>
additionalLocations
=
new
[]
{
additionalLocation
};
IEnumerable
<
Location
>
additionalLocations
=
new
[]
{
Location
.
Create
(
@"Relative Additional\Location.cs"
,
span
,
position
),
Location
.
Create
(
@"a:cannot/interpret/as\uri"
,
span
,
position
),
};
logger
.
LogDiagnostic
(
Diagnostic
.
Create
(
descriptor
,
mainLocation
,
additionalLocations
));
}
string
expected
=
string
expected
=
@"{
""$schema"": ""http://json.schemastore.org/sarif-1.0.0
-beta.5
"",
""version"": ""1.0.0
-beta.5
"",
""$schema"": ""http://json.schemastore.org/sarif-1.0.0"",
""version"": ""1.0.0"",
""runs"": [
{
""tool"": {
""name"": ""toolName"",
""version"": ""1.2.3.4"",
""fileVersion"": ""1.2.3.4"",
""semanticVersion"": ""1.2.3""
""semanticVersion"": ""1.2.3"",
""language"": ""fr-CA""
},
""results"": [
{
...
...
@@ -47,7 +54,7 @@ public void AdditionalLocationsAsRelatedLocations()
""locations"": [
{
""resultFile"": {
""uri"": ""file:///Z:/MainLocation.cs"",
""uri"": ""file:///Z:/Main
%20
Location.cs"",
""region"": {
""startLine"": 1,
""startColumn"": 1,
...
...
@@ -60,7 +67,18 @@ public void AdditionalLocationsAsRelatedLocations()
""relatedLocations"": [
{
""physicalLocation"": {
""uri"": ""file:///Z:/AdditionalLocation.cs"",
""uri"": ""Relative%20Additional/Location.cs"",
""region"": {
""startLine"": 1,
""startColumn"": 1,
""endLine"": 1,
""endColumn"": 1
}
}
},
{
""physicalLocation"": {
""uri"": ""a%3Acannot%2Finterpret%2Fas%5Curi"",
""region"": {
""startLine"": 1,
""startColumn"": 1,
...
...
@@ -93,14 +111,29 @@ public void AdditionalLocationsAsRelatedLocations()
public
void
DescriptorIdCollision
()
{
var
descriptors
=
new
[]
{
new
DiagnosticDescriptor
(
"TST001.001"
,
"_TST001.001_"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
// Toughest case: generation of TST001-001 collides with with actual TST001-001 and must be bumped to TST001-002
new
DiagnosticDescriptor
(
"TST001-001"
,
"_TST001-001_"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST001"
,
"_TST001_"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST001"
,
"_TST001.002_"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST001"
,
"_TST001.003_"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST001"
,
"_TST001-002_"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST001"
,
"_TST001-003_"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
// Descriptors with same values should not get distinct entries in log
new
DiagnosticDescriptor
(
"TST002"
,
""
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST002"
,
""
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
// Changing only the message format (which we do not write out) should not produce a distinct entry in log.
new
DiagnosticDescriptor
(
"TST002"
,
""
,
"messageFormat"
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
// Changing any property that we do write out should create a distinct entry
new
DiagnosticDescriptor
(
"TST002"
,
"title_001"
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST002"
,
""
,
""
,
"category_002"
,
DiagnosticSeverity
.
Warning
,
true
),
new
DiagnosticDescriptor
(
"TST002"
,
""
,
""
,
""
,
DiagnosticSeverity
.
Error
/*003*/
,
true
),
new
DiagnosticDescriptor
(
"TST002"
,
""
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
isEnabledByDefault
:
false
/*004*/
),
new
DiagnosticDescriptor
(
"TST002"
,
""
,
""
,
""
,
DiagnosticSeverity
.
Warning
,
true
,
"description_005"
),
};
var
stream
=
new
MemoryStream
();
using
(
var
logger
=
new
ErrorLogger
(
stream
,
"toolName"
,
"1.2.3.4"
,
new
Version
(
1
,
2
,
3
,
4
),
CultureInfo
.
InvariantCulture
))
using
(
var
logger
=
new
ErrorLogger
(
stream
,
"toolName"
,
"1.2.3.4"
,
new
Version
(
1
,
2
,
3
,
4
),
new
CultureInfo
(
"en-US"
)
))
{
for
(
int
i
=
0
;
i
<
2
;
i
++)
{
...
...
@@ -113,19 +146,20 @@ public void DescriptorIdCollision()
string
expected
=
@"{
""$schema"": ""http://json.schemastore.org/sarif-1.0.0
-beta.5
"",
""version"": ""1.0.0
-beta.5
"",
""$schema"": ""http://json.schemastore.org/sarif-1.0.0"",
""version"": ""1.0.0"",
""runs"": [
{
""tool"": {
""name"": ""toolName"",
""version"": ""1.2.3.4"",
""fileVersion"": ""1.2.3.4"",
""semanticVersion"": ""1.2.3""
""semanticVersion"": ""1.2.3"",
""language"": ""en-US""
},
""results"": [
{
""ruleId"": ""TST001
.
001"",
""ruleId"": ""TST001
-
001"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
...
...
@@ -140,7 +174,7 @@ public void DescriptorIdCollision()
},
{
""ruleId"": ""TST001"",
""ruleKey"": ""TST001
.
002"",
""ruleKey"": ""TST001
-
002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
...
...
@@ -148,14 +182,73 @@ public void DescriptorIdCollision()
},
{
""ruleId"": ""TST001"",
""ruleKey"": ""TST001.003"",
""ruleKey"": ""TST001-003"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""level"": ""warning"",
""message"": ""messageFormat"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-001"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST001.001"",
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-003"",
""level"": ""error""
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-004"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-005"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST001-001"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
...
...
@@ -170,7 +263,7 @@ public void DescriptorIdCollision()
},
{
""ruleId"": ""TST001"",
""ruleKey"": ""TST001
.
002"",
""ruleKey"": ""TST001
-
002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
...
...
@@ -178,7 +271,66 @@ public void DescriptorIdCollision()
},
{
""ruleId"": ""TST001"",
""ruleKey"": ""TST001.003"",
""ruleKey"": ""TST001-003"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""level"": ""warning"",
""message"": ""messageFormat"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-001"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-002"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-003"",
""level"": ""error""
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-004"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
}
},
{
""ruleId"": ""TST002"",
""ruleKey"": ""TST002-005"",
""level"": ""warning"",
""properties"": {
""warningLevel"": 1
...
...
@@ -194,25 +346,70 @@ public void DescriptorIdCollision()
""isEnabledByDefault"": true
}
},
""TST001
.
001"": {
""id"": ""TST001
.
001"",
""shortDescription"": ""_TST001
.
001_"",
""TST001
-
001"": {
""id"": ""TST001
-
001"",
""shortDescription"": ""_TST001
-
001_"",
""defaultLevel"": ""warning"",
""properties"": {
""isEnabledByDefault"": true
}
},
""TST001
.
002"": {
""TST001
-
002"": {
""id"": ""TST001"",
""shortDescription"": ""_TST001
.
002_"",
""shortDescription"": ""_TST001
-
002_"",
""defaultLevel"": ""warning"",
""properties"": {
""isEnabledByDefault"": true
}
},
""TST001
.
003"": {
""TST001
-
003"": {
""id"": ""TST001"",
""shortDescription"": ""_TST001.003_"",
""shortDescription"": ""_TST001-003_"",
""defaultLevel"": ""warning"",
""properties"": {
""isEnabledByDefault"": true
}
},
""TST002"": {
""id"": ""TST002"",
""defaultLevel"": ""warning"",
""properties"": {
""isEnabledByDefault"": true
}
},
""TST002-001"": {
""id"": ""TST002"",
""shortDescription"": ""title_001"",
""defaultLevel"": ""warning"",
""properties"": {
""isEnabledByDefault"": true
}
},
""TST002-002"": {
""id"": ""TST002"",
""defaultLevel"": ""warning"",
""properties"": {
""category"": ""category_002"",
""isEnabledByDefault"": true
}
},
""TST002-003"": {
""id"": ""TST002"",
""defaultLevel"": ""error"",
""properties"": {
""isEnabledByDefault"": true
}
},
""TST002-004"": {
""id"": ""TST002"",
""defaultLevel"": ""warning"",
""properties"": {
""isEnabledByDefault"": false
}
},
""TST002-005"": {
""id"": ""TST002"",
""fullDescription"": ""description_005"",
""defaultLevel"": ""warning"",
""properties"": {
""isEnabledByDefault"": true
...
...
src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs
浏览文件 @
cd21f84c
...
...
@@ -84,6 +84,11 @@ internal Version GetAssemblyVersion()
return
typeof
(
CommonCompiler
).
GetTypeInfo
().
Assembly
.
GetName
().
Version
;
}
internal
string
GetCultureName
()
{
return
Culture
.
Name
;
}
internal
virtual
Func
<
string
,
MetadataReferenceProperties
,
PortableExecutableReference
>
GetMetadataProvider
()
{
return
(
path
,
properties
)
=>
MetadataReference
.
CreateFromFile
(
path
,
properties
);
...
...
src/Compilers/Core/Portable/CommandLine/ErrorLogger.cs
浏览文件 @
cd21f84c
...
...
@@ -37,26 +37,22 @@ public ErrorLogger(Stream stream, string toolName, string toolFileVersion, Versi
_culture
=
culture
;
_writer
.
WriteObjectStart
();
// root
_writer
.
Write
(
"$schema"
,
"http://json.schemastore.org/sarif-1.0.0
-beta.5
"
);
_writer
.
Write
(
"version"
,
"1.0.0
-beta.5
"
);
_writer
.
Write
(
"$schema"
,
"http://json.schemastore.org/sarif-1.0.0"
);
_writer
.
Write
(
"version"
,
"1.0.0"
);
_writer
.
WriteArrayStart
(
"runs"
);
_writer
.
WriteObjectStart
();
// run
WriteToolInfo
(
toolName
,
toolFileVersion
,
toolAssemblyVersion
);
_writer
.
WriteObjectStart
(
"tool"
);
_writer
.
Write
(
"name"
,
toolName
);
_writer
.
Write
(
"version"
,
toolAssemblyVersion
.
ToString
());
_writer
.
Write
(
"fileVersion"
,
toolFileVersion
);
_writer
.
Write
(
"semanticVersion"
,
toolAssemblyVersion
.
ToString
(
fieldCount
:
3
));
_writer
.
Write
(
"language"
,
culture
.
Name
);
_writer
.
WriteObjectEnd
();
// tool
_writer
.
WriteArrayStart
(
"results"
);
}
private
void
WriteToolInfo
(
string
name
,
string
fileVersion
,
Version
assemblyVersion
)
{
_writer
.
WriteObjectStart
(
"tool"
);
_writer
.
Write
(
"name"
,
name
);
_writer
.
Write
(
"version"
,
assemblyVersion
.
ToString
());
_writer
.
Write
(
"fileVersion"
,
fileVersion
);
_writer
.
Write
(
"semanticVersion"
,
assemblyVersion
.
ToString
(
fieldCount
:
3
));
_writer
.
WriteObjectEnd
();
}
public
void
LogDiagnostic
(
Diagnostic
diagnostic
)
{
_writer
.
WriteObjectStart
();
// result
...
...
@@ -155,22 +151,36 @@ private static bool HasPath(Location location)
return
!
string
.
IsNullOrEmpty
(
location
.
GetLineSpan
().
Path
);
}
private
static
readonly
Uri
_fileRoot
=
new
Uri
(
"file:///"
);
private
static
string
GetUri
(
string
path
)
{
Debug
.
Assert
(!
string
.
IsNullOrEmpty
(
path
));
// Note that in general, these "paths" are opaque strings to be
// interpreted by resolvers (see SyntaxTree.FilePath documentation).
// Common case: absolute path -> absolute URI
Uri
uri
;
if
(
Uri
.
TryCreate
(
path
,
UriKind
.
Absolute
,
out
uri
))
{
// We use Uri.AbsoluteUri and not Uri.ToString() because Uri.ToString()
// is unescaped (e.g. spaces remain unreplaced by %20) and therefore
// not well-formed.
return
uri
.
AbsoluteUri
;
}
if
(!
Uri
.
TryCreate
(
path
,
UriKind
.
RelativeOrAbsolute
,
out
uri
))
// First fallback attempt: attempt to interpret as relative path/URI.
// (Perhaps the resolver works that way.)
if
(
Uri
.
TryCreate
(
path
,
UriKind
.
Relative
,
out
uri
))
{
// The only constraint on paths are that they can be interpreted by
// various resolvers so there is no guarantee we can turn the arbitrary string
// in to a URI. If our attempt to do so fails, use the original string as the
// "URI".
return
path
;
// There is no AbsoluteUri equivalent for relative URI references and ToString()
// won't escape without this relative -> absolute -> relative trick.
return
_fileRoot
.
MakeRelativeUri
(
new
Uri
(
_fileRoot
,
uri
)).
ToString
();
}
return
uri
.
ToString
();
// Last resort: UrlEncode the whole opaque string.
return
System
.
Net
.
WebUtility
.
UrlEncode
(
path
);
}
private
void
WriteProperties
(
Diagnostic
diagnostic
)
...
...
@@ -317,7 +327,7 @@ private sealed class DiagnosticDescriptorSet
private
Dictionary
<
string
,
int
>
_counters
=
new
Dictionary
<
string
,
int
>();
// DiagnosticDescriptor -> unique key
private
Dictionary
<
DiagnosticDescriptor
,
string
>
_keys
=
new
Dictionary
<
DiagnosticDescriptor
,
string
>();
private
Dictionary
<
DiagnosticDescriptor
,
string
>
_keys
=
new
Dictionary
<
DiagnosticDescriptor
,
string
>(
new
Comparer
()
);
/// <summary>
/// The total number of descriptors in the set.
...
...
@@ -355,7 +365,7 @@ public string Add(DiagnosticDescriptor descriptor)
do
{
_counters
[
descriptor
.
Id
]
=
++
counter
;
key
=
descriptor
.
Id
+
"
.
"
+
counter
.
ToString
(
"000"
,
CultureInfo
.
InvariantCulture
);
key
=
descriptor
.
Id
+
"
-
"
+
counter
.
ToString
(
"000"
,
CultureInfo
.
InvariantCulture
);
}
while
(
_counters
.
ContainsKey
(
key
));
_keys
.
Add
(
descriptor
,
key
);
...
...
@@ -381,6 +391,72 @@ public string Add(DiagnosticDescriptor descriptor)
list
.
Sort
((
x
,
y
)
=>
string
.
CompareOrdinal
(
x
.
Key
,
y
.
Key
));
return
list
;
}
/// <summary>
/// Compares descriptors by the values that we write to the log and nothing else.
///
/// We cannot just use <see cref="DiagnosticDescriptor"/>'s built-in implementation
/// of <see cref="IEquatable{DiagnosticDescriptor}"/> for two reasons:
///
/// 1. <see cref="DiagnosticDescriptor.MessageFormat"/> is part of that built-in
/// equatability, but we do not write it out, and so descriptors differing only
/// by MessageFormat (common) would lead to duplicate rule metadata entries in
/// the log.
///
/// 2. <see cref="DiagnosticDescriptor.CustomTags"/> is *not* part of that built-in
/// equatability, but we do write them out, and so descriptors differening only
/// by CustomTags (rare) would cause only one set of tags to be reported in the
/// log.
/// </summary>
private
sealed
class
Comparer
:
IEqualityComparer
<
DiagnosticDescriptor
>
{
public
bool
Equals
(
DiagnosticDescriptor
x
,
DiagnosticDescriptor
y
)
{
if
(
ReferenceEquals
(
x
,
y
))
{
return
true
;
}
if
(
ReferenceEquals
(
x
,
null
)
||
ReferenceEquals
(
y
,
null
))
{
return
false
;
}
// The properties are guaranteed to be non-null by DiagnosticDescriptor invariants.
Debug
.
Assert
(
x
.
Description
!=
null
&&
x
.
Title
!=
null
&&
x
.
CustomTags
!=
null
);
Debug
.
Assert
(
y
.
Description
!=
null
&&
y
.
Title
!=
null
&&
y
.
CustomTags
!=
null
);
return
(
x
.
Category
==
y
.
Category
&&
x
.
DefaultSeverity
==
y
.
DefaultSeverity
&&
x
.
Description
.
Equals
(
y
.
Description
)
&&
x
.
HelpLinkUri
==
y
.
HelpLinkUri
&&
x
.
Id
==
y
.
Id
&&
x
.
IsEnabledByDefault
==
y
.
IsEnabledByDefault
&&
x
.
Title
.
Equals
(
y
.
Title
)
&&
x
.
CustomTags
.
SequenceEqual
(
y
.
CustomTags
));
}
public
int
GetHashCode
(
DiagnosticDescriptor
obj
)
{
if
(
ReferenceEquals
(
obj
,
null
))
{
return
0
;
}
// The properties are guaranteed to be non-null by DiagnosticDescriptor invariants.
Debug
.
Assert
(
obj
.
Category
!=
null
&&
obj
.
Description
!=
null
&&
obj
.
HelpLinkUri
!=
null
&&
obj
.
Id
!=
null
&&
obj
.
Title
!=
null
&&
obj
.
CustomTags
!=
null
);
return
Hash
.
Combine
(
obj
.
Category
.
GetHashCode
(),
Hash
.
Combine
(
obj
.
DefaultSeverity
.
GetHashCode
(),
Hash
.
Combine
(
obj
.
Description
.
GetHashCode
(),
Hash
.
Combine
(
obj
.
HelpLinkUri
.
GetHashCode
(),
Hash
.
Combine
(
obj
.
Id
.
GetHashCode
(),
Hash
.
Combine
(
obj
.
IsEnabledByDefault
.
GetHashCode
(),
Hash
.
Combine
(
obj
.
Title
.
GetHashCode
(),
Hash
.
CombineValues
(
obj
.
CustomTags
))))))));
}
}
}
}
}
...
...
src/Test/Utilities/Shared/Diagnostics/DiagnosticExtensions.cs
浏览文件 @
cd21f84c
...
...
@@ -308,18 +308,20 @@ internal static string GetExpectedErrorLogHeader(string actualOutput, CommonComp
var
expectedVersion
=
compiler
.
GetAssemblyVersion
();
var
expectedSemanticVersion
=
compiler
.
GetAssemblyVersion
().
ToString
(
fieldCount
:
3
);
var
expectedFileVersion
=
compiler
.
GetAssemblyFileVersion
();
var
expectedLanguage
=
compiler
.
GetCultureName
();
return
string
.
Format
(
@"{{
""$schema"": ""http://json.schemastore.org/sarif-1.0.0
-beta.5
"",
""version"": ""1.0.0
-beta.5
"",
""$schema"": ""http://json.schemastore.org/sarif-1.0.0"",
""version"": ""1.0.0"",
""runs"": [
{{
""tool"": {{
""name"": ""{0}"",
""version"": ""{1}"",
""fileVersion"": ""{2}"",
""semanticVersion"": ""{3}""
}},"
,
expectedToolName
,
expectedVersion
,
expectedFileVersion
,
expectedSemanticVersion
);
""semanticVersion"": ""{3}"",
""language"": ""{4}""
}},"
,
expectedToolName
,
expectedVersion
,
expectedFileVersion
,
expectedSemanticVersion
,
expectedLanguage
);
}
public
static
string
Stringize
(
this
Diagnostic
e
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录