-
Notifications
You must be signed in to change notification settings - Fork 757
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
be0b3b7
commit 2431efa
Showing
7 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
38 changes: 38 additions & 0 deletions
38
src/Bicep.Core.UnitTests/Diagnostics/LinterRuleTests/UseSafeAccessRuleTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using Bicep.Core.Analyzers.Linter.Rules; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
|
||
namespace Bicep.Core.UnitTests.Diagnostics.LinterRuleTests; | ||
|
||
[TestClass] | ||
public class UseSafeAccessRuleTests : LinterRuleTestsBase | ||
{ | ||
private void AssertCodeFix(string inputFile, string resultFile) | ||
=> AssertCodeFix(UseSafeAccessRule.Code, "Use the safe access (.?) operator", inputFile, resultFile); | ||
|
||
private void AssertNoDiagnostics(string inputFile) | ||
=> AssertLinterRuleDiagnostics(UseSafeAccessRule.Code, inputFile, [], new(OnCompileErrors.Ignore, IncludePosition.None)); | ||
|
||
[TestMethod] | ||
public void Codefix_fixes_syntax_which_can_be_simplified() => AssertCodeFix(""" | ||
param foo object | ||
var test = contai|ns(foo, 'bar') ? foo.bar : 'baz' | ||
""", """ | ||
param foo object | ||
var test = foo.?bar ?? 'baz' | ||
"""); | ||
|
||
[TestMethod] | ||
public void Rule_ignores_syntax_which_cannot_be_simplified() => AssertNoDiagnostics(""" | ||
param foo object | ||
var test = contains(foo, 'bar') ? foo.baz : 'baz' | ||
"""); | ||
|
||
[TestMethod] | ||
public void Rule_ignores_syntax_which_cannot_be_simplified_2() => AssertNoDiagnostics(""" | ||
param foo object | ||
var test = contains(foo, 'bar') ? bar.bar : 'baz' | ||
"""); | ||
} |
65 changes: 65 additions & 0 deletions
65
src/Bicep.Core/Analyzers/Linter/Rules/UseSafeAccessRule.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using Bicep.Core.CodeAction; | ||
using Bicep.Core.Diagnostics; | ||
using Bicep.Core.Parsing; | ||
using Bicep.Core.Semantics; | ||
using Bicep.Core.Semantics.Namespaces; | ||
using Bicep.Core.Syntax; | ||
using Bicep.Core.Syntax.Comparers; | ||
using Bicep.Core.Syntax.Visitors; | ||
|
||
namespace Bicep.Core.Analyzers.Linter.Rules; | ||
|
||
public sealed class UseSafeAccessRule : LinterRuleBase | ||
{ | ||
public new const string Code = "use-safe-access"; | ||
|
||
public UseSafeAccessRule() : base( | ||
code: Code, | ||
description: CoreResources.UseSafeAccessRule_Description, | ||
LinterRuleCategory.BestPractice, | ||
docUri: new Uri($"https://aka.ms/bicep/linter/{Code}")) | ||
{ } | ||
|
||
public override IEnumerable<IDiagnostic> AnalyzeInternal(SemanticModel model, DiagnosticLevel diagnosticLevel) | ||
{ | ||
foreach (var ternary in SyntaxAggregator.AggregateByType<TernaryOperationSyntax>(model.Root.Syntax)) | ||
{ | ||
if (SemanticModelHelper.TryGetNamedFunction(model, SystemNamespaceType.BuiltInName, "contains", ternary.ConditionExpression) is not {} functionCall || | ||
functionCall.Arguments.Length != 2 || | ||
functionCall.Arguments[1].Expression is not StringSyntax containsString || | ||
containsString.TryGetLiteralValue() is not {} propertyName) | ||
{ | ||
continue; | ||
} | ||
|
||
if (ternary.TrueExpression is not PropertyAccessSyntax truePropertyAccess || | ||
!truePropertyAccess.PropertyName.NameEquals(propertyName)) | ||
{ | ||
continue; | ||
} | ||
|
||
if (!SyntaxIgnoringTriviaComparer.Instance.Equals(functionCall.Arguments[0].Expression, truePropertyAccess.BaseExpression)) | ||
{ | ||
continue; | ||
} | ||
|
||
var replacement = SyntaxFactory.CreateBinaryOperationSyntax( | ||
SyntaxFactory.CreateSafePropertyAccess(truePropertyAccess.BaseExpression, propertyName), | ||
TokenType.DoubleQuestion, | ||
ternary.FalseExpression); | ||
|
||
yield return CreateFixableDiagnosticForSpan( | ||
diagnosticLevel, | ||
ternary.Span, | ||
new CodeFix( | ||
CoreResources.UseSafeAccessRule_CodeFix, | ||
isPreferred: true, | ||
CodeFixKind.QuickFix, | ||
new CodeReplacement(ternary.Span, replacement.ToString())), | ||
CoreResources.UseSafeAccessRule_MessageFormat); | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters