Skip to content

Commit 68da5b8

Browse files
committed
Add compile time constant analyzer
1 parent 0c4c626 commit 68da5b8

9 files changed

+175
-7
lines changed

README.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,60 @@
1-
# resharper-structured-logging
1+
# ReSharper Structured Logging
2+
[![Build status](https://ci.appveyor.com/api/projects/status/c4riih64hbd4sebw?svg=true)](https://ci.appveyor.com/project/olsh/resharper-structured-logging)
3+
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=resharper-structured-logging&metric=alert_status)](https://sonarcloud.io/dashboard?id=resharper-structured-logging)
24

35
An extension for ReSharper that highlights structured logging templates and contains some useful analyzers
6+
7+
At the moment it supports Serilog, NLog, and Microsoft.Extensions.Logging
8+
9+
## Highlighting
10+
11+
![Highlighting](https://github.com/olsh/resharper-structured-logging/raw/master/images/highlighting.png)
12+
13+
## Analyzers
14+
15+
### Duplicate template property
16+
17+
Noncompliant Code Example:
18+
```csharp
19+
Log.Error("Disk quota {Quota} MB exceeded by {Quota}", quota, user);
20+
```
21+
22+
Compliant Solution:
23+
```csharp
24+
Log.Error("Disk quota {Quota} MB exceeded by {User}", quota, user);
25+
```
26+
27+
### Exception passed as a template argument
28+
29+
Noncompliant Code Example:
30+
```csharp
31+
catch (Exception exception)
32+
{
33+
Log.Error(ex, "Disk quota {Quota} MB exceeded {Exception}", quota, exception);
34+
}
35+
```
36+
37+
Compliant Solution:
38+
```csharp
39+
catch (Exception exception)
40+
{
41+
Log.Error(exception, "Disk quota {Quota} MB exceeded", quota);
42+
}
43+
```
44+
45+
### Message template is not a compile time constant
46+
47+
Noncompliant Code Examples:
48+
```csharp
49+
Log.Error($"Disk quota {quota} MB exceeded by {user}");
50+
```
51+
52+
```csharp
53+
Log.Error(string.Format("Disk quota {0} MB exceeded by {1}", quota, user));
54+
```
55+
56+
57+
Compliant Solution:
58+
```csharp
59+
Log.Error("Disk quota {Quota} MB exceeded by {User}", quota, user);
60+
```

images/highlighting.png

9.97 KB
Loading
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using JetBrains.ReSharper.Feature.Services.Daemon;
2+
using JetBrains.ReSharper.Psi.CSharp.Tree;
3+
using JetBrains.ReSharper.Psi.Tree;
4+
5+
using ReSharper.Structured.Logging.Extensions;
6+
using ReSharper.Structured.Logging.Highlighting;
7+
8+
namespace ReSharper.Structured.Logging.Analyzer
9+
{
10+
[ElementProblemAnalyzer(typeof(IInvocationExpression))]
11+
public class CompileTimeConstantTemplateAnalyzer : ElementProblemAnalyzer<IInvocationExpression>
12+
{
13+
protected override void Run(
14+
IInvocationExpression element,
15+
ElementProblemAnalyzerData data,
16+
IHighlightingConsumer consumer)
17+
{
18+
var templateArgument = element.GetTemplateArgument();
19+
if (templateArgument == null)
20+
{
21+
return;
22+
}
23+
24+
if (templateArgument.Value.IsConstantValue())
25+
{
26+
return;
27+
}
28+
29+
consumer.AddHighlighting(new TemplateIsNotCompileTimeConstantWarning(templateArgument.Expression.GetDocumentRange()));
30+
}
31+
}
32+
}

src/ReSharper.Structured.Logging/Analyzer/CorrectExceptionPassingAnalyzer.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ protected override void Run(
2424
return;
2525
}
2626

27-
var stringLiteral = StringLiteralAltererUtil.TryCreateStringLiteralByExpression(templateArgument.Value);
28-
if (stringLiteral == null)
29-
{
30-
return;
31-
}
32-
3327
var templateArgumentIndex = templateArgument.IndexOf();
3428
var exceptionType = element.PsiModule.GetPredefinedType().TryGetType(PredefinedType.EXCEPTION_FQN);
3529
if (exceptionType == null)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using JetBrains.DocumentModel;
2+
using JetBrains.ReSharper.Feature.Services.Daemon;
3+
using JetBrains.ReSharper.Psi.CSharp;
4+
5+
using ReSharper.Structured.Logging.Highlighting;
6+
7+
[assembly:
8+
RegisterConfigurableSeverity(TemplateIsNotCompileTimeConstantWarning.SeverityId, null, HighlightingGroupIds.CompilerWarnings,
9+
TemplateIsNotCompileTimeConstantWarning.Message, TemplateIsNotCompileTimeConstantWarning.Message,
10+
Severity.WARNING)]
11+
12+
namespace ReSharper.Structured.Logging.Highlighting
13+
{
14+
[ConfigurableSeverityHighlighting(
15+
SeverityId,
16+
CSharpLanguage.Name,
17+
OverlapResolve = OverlapResolveKind.WARNING,
18+
ToolTipFormatString = Message)]
19+
public class TemplateIsNotCompileTimeConstantWarning : IHighlighting
20+
{
21+
public const string SeverityId = "TemplateIsNotCompileTimeConstantProblem";
22+
23+
public const string Message = "Message template should be compile time constant";
24+
25+
private readonly DocumentRange _documentRange;
26+
27+
public TemplateIsNotCompileTimeConstantWarning(DocumentRange documentRange)
28+
{
29+
_documentRange = documentRange;
30+
}
31+
32+
public string ErrorStripeToolTip => ToolTip;
33+
34+
public string ToolTip => Message;
35+
36+
public DocumentRange CalculateRange()
37+
{
38+
return _documentRange;
39+
}
40+
41+
public bool IsValid()
42+
{
43+
return _documentRange.IsValid();
44+
}
45+
}
46+
}

src/ReSharper.Structured.Logging/ReSharper.Structured.Logging.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@
324324
</Reference>
325325
</ItemGroup>
326326
<ItemGroup>
327+
<Compile Include="Analyzer\CompileTimeConstantTemplateAnalyzer.cs" />
327328
<Compile Include="Analyzer\CorrectExceptionPassingAnalyzer.cs" />
328329
<Compile Include="Analyzer\DuplicatePropertiesTemplateAnalyzer.cs" />
329330
<Compile Include="Analyzer\TemplateFormatAnalyzer.cs" />
@@ -333,6 +334,7 @@
333334
<Compile Include="Highlighting\TemplateFormatStringArgumentIsNotUsedWarning.cs" />
334335
<Compile Include="Highlighting\TemplateFormatStringInexistingArgumentWarning.cs" />
335336
<Compile Include="Highlighting\TemplateFormatItemAndMatchingArgumentHighlighter.cs" />
337+
<Compile Include="Highlighting\TemplateIsNotCompileTimeConstantWarning.cs" />
336338
<Compile Include="Properties\AssemblyInfo.cs" />
337339
<Compile Include="Serilog\Core\IMessageTemplateParser.cs" />
338340
<Compile Include="Serilog\Events\MessageTemplate.cs" />
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using Serilog;
3+
4+
namespace ConsoleApp
5+
{
6+
public static class Program
7+
{
8+
public static void Main()
9+
{
10+
Log.Logger.Information($"{DateTime.Now} {{Error}}", new Exception());
11+
}
12+
}
13+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using Serilog;
3+
4+
namespace ConsoleApp
5+
{
6+
public static class Program
7+
{
8+
public static void Main()
9+
{
10+
Log.Logger.Information($"{DateTime.Now} |{{|(0)Error|}}|(1)", |new Exception()|(2));
11+
}
12+
}
13+
}
14+
15+
---------------------------------------------------------
16+
(0): ReSharper String Escape Character 1:
17+
(1): ReSharper String Escape Character 1:
18+
(2): ReSharper Warning: Exception should be passed to the exception argument

test/src/Analyzer/CorrectExceptionPassingAnalyzerTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,11 @@ public void TestSerilogMultipleExceptionPassing()
2121
{
2222
DoNamedTest2();
2323
}
24+
25+
[Test]
26+
public void TestSerilogIncorrectExceptionPassingDynamicTemplate()
27+
{
28+
DoNamedTest2();
29+
}
2430
}
2531
}

0 commit comments

Comments
 (0)