Skip to content

Commit

Permalink
Added a new feature to inspect constructors.
Browse files Browse the repository at this point in the history
Update SDK
  • Loading branch information
Mahmoud Fakhoury authored and Mahmoud Fakhoury committed Feb 8, 2025
1 parent cafeea0 commit 83b5624
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 214 deletions.
4 changes: 2 additions & 2 deletions build/Old Build/ExceptionalDevs.Exceptional.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<package>
<metadata>
<id>ExceptionalDevs.Exceptional.MF</id>
<version>2024.3.2</version>
<version>2025.2.8</version>
<title>Exceptional by MF</title>
<description>Analyzes thrown and documented C# exceptions and suggests improvements.</description>
<authors>Mahmoud Fakhoury</authors>
<projectUrl>https://github.com/hhu-mahmoud/ExceptionalReSharper</projectUrl>
<copyright>Copyright © 2024 MF</copyright>
<copyright>Copyright © 2025 MF</copyright>
<tags>Exception XMLdoc</tags>
<licenseUrl>https://github.com/hhu-mahmoud/ExceptionalReSharper/blob/master/LICENSE.md</licenseUrl>
<dependencies>
Expand Down
Binary file modified build/Old Build/lib/ReSharper.Exceptional.MF.dll
Binary file not shown.
Binary file not shown.
8 changes: 7 additions & 1 deletion src/Exceptional.Playground/CatchAllClause.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
namespace Exceptional.Playground

namespace Exceptional.Playground
{
using System;
using System.Security;

public class CatchAllClause
{
#region methods

public CatchAllClause()
{
throw new SecurityException();
}

public void Test01()
{
Expand Down
1 change: 1 addition & 0 deletions src/Exceptional.Playground/Exceptional.Playground.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<Compile Include="Demonstration.cs" />
<Compile Include="EventMayThrowException.cs" />
<Compile Include="Fixed\CSharp7Features.cs" />
<Compile Include="Fixed\InspectConstructor.cs" />
<Compile Include="Fixed\EventRegistrationShowsWarning.cs" />
<Compile Include="Fixed\AddingElementToListDoesNotShowException.cs" />
<Compile Include="Fixed\ExceptionOnInterfaceMarkedAsUnnecessary.cs" />
Expand Down
1 change: 0 additions & 1 deletion src/Exceptional.Playground/Fixed/DisableWarnings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ public class DisableWarnings
{
public void Foo()
{
// ReSharper disable once ExceptionNotDocumentedOptional
throw new NotImplementedException("Bar"); // no warning
// ReSharper restore once ExceptionNotDocumentedOptional
throw new NotImplementedException("Bar"); // warning
Expand Down
13 changes: 13 additions & 0 deletions src/Exceptional.Playground/Fixed/InspectConstructor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;

namespace Exceptional.Playground.Fixed
{
public class InspectConstructor
{
public InspectConstructor()
{
throw new NotImplementedException("Bar"); // no warning (Constructor)
}

}
}
2 changes: 2 additions & 0 deletions src/Exceptional/Analyzers/AnalyzerBase.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using JetBrains.ReSharper.UnitTestExplorer.Resources;

namespace ReSharper.Exceptional.MF.Analyzers
{
using Models;
Expand Down
11 changes: 10 additions & 1 deletion src/Exceptional/Analyzers/IsDocumentedExceptionThrownAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ public override void Visit(ExceptionDocCommentModel exceptionDocumentation)
{
return;
}
if (IsConstructor(exceptionDocumentation))
{
return;
}
if (IsAbstractOrInterfaceMethod(exceptionDocumentation))
{
return;
Expand All @@ -37,7 +41,12 @@ public override void Visit(ExceptionDocCommentModel exceptionDocumentation)
: new ExceptionNotThrownHighlighting(exceptionDocumentation);
ServiceLocator.StageProcess.AddHighlighting(highlighting, exceptionDocumentation.DocumentRange);
}

private static bool IsConstructor(ModelBase exceptionDocumentation)
{
var declaredElement = (exceptionDocumentation.AnalyzeUnit as ConstructorDeclarationModel)?.Node.DeclaredElement;
var isConstructor = declaredElement != null;
return isConstructor && !ServiceLocator.Settings.InspectConstructors;
}
private static bool IsAbstractOrInterfaceMethod(ModelBase exceptionDocumentation)
{
var declaredElement = (exceptionDocumentation.AnalyzeUnit as MethodDeclarationModel)?.Node.DeclaredElement;
Expand Down
11 changes: 10 additions & 1 deletion src/Exceptional/Analyzers/IsThrownExceptionDocumentedAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public override void Visit(ThrownExceptionModel thrownException)
{
return;
}
if (IsConstructor(thrownException))
{
return;
}
if (!thrownException.AnalyzeUnit.IsInspectionRequired || thrownException.IsCaught || thrownException.IsExceptionDocumented)
{
return;
Expand All @@ -48,7 +52,12 @@ public override void Visit(ThrownExceptionModel thrownException)
ServiceLocator.StageProcess.AddHighlighting(highlighting, thrownException.DocumentRange);
}
}

private static bool IsConstructor(ModelBase thrownException)
{
var declaredElement = (thrownException.AnalyzeUnit as ConstructorDeclarationModel)?.Node.DeclaredElement;
var isConstructor = declaredElement != null;
return isConstructor && !ServiceLocator.Settings.InspectConstructors;
}
private bool IsSubtypeDocumented(ThrownExceptionModel thrownException)
{
if (thrownException.IsThrownFromThrowStatement)
Expand Down
6 changes: 3 additions & 3 deletions src/Exceptional/Exceptional.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
<Version>2024.3.0</Version>
</PackageReference>
<PackageReference Include="JetBrains.Lifetimes">
<Version>2024.3.1</Version>
<Version>2025.1.1</Version>
</PackageReference>
<PackageReference Include="JetBrains.RdFramework">
<Version>2024.3.1</Version>
<Version>2025.1.1</Version>
</PackageReference>
<PackageReference Include="JetBrains.ReSharper.SDK" Version="2021.3.2">
<Version>2024.3.2</Version>
<Version>2024.3.5</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
5 changes: 2 additions & 3 deletions src/Exceptional/ExceptionalDaemonStageProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,12 @@ public void AddHighlighting(IHighlighting highlighting, DocumentRange range)
/// <exception cref="Exception">A delegate callback throws an exception.</exception>
public override void Execute(Action<DaemonStageResult> commiter)
{
var file = ServiceLocator.Process.SourceFile.GetTheOnlyPsiFile(CSharpLanguage.Instance) as ICSharpFile;
if (file == null)
if (ServiceLocator.Process.SourceFile.GetTheOnlyPsiFile(CSharpLanguage.Instance) is not ICSharpFile file)
{
return;
}
var elementProcessor = new ExceptionalRecursiveElementProcessor(this);
file.ProcessDescendants(elementProcessor);
file.ProcessThisAndDescendants(elementProcessor);
if (ServiceLocator.Process.InterruptFlag)
{
throw new OperationCanceledException();
Expand Down
11 changes: 6 additions & 5 deletions src/Exceptional/Models/AnalyzeUnitModelBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ public bool IsInspectionRequired
{
get
{
var accessRightsOwner = Node as IAccessRightsOwner;
if (accessRightsOwner == null)
if (Node is not IAccessRightsOwner accessRightsOwner)
{
return false;
}
Expand All @@ -48,9 +47,11 @@ public bool IsInspectionRequired
var inspectProtectedMethods = ServiceLocator.Settings.InspectProtectedMethods;
var inspectPrivateMethods = ServiceLocator.Settings.InspectPrivateMethods;
var rights = accessRightsOwner.GetAccessRights();
return rights == AccessRights.PUBLIC && inspectPublicMethods || rights == AccessRights.INTERNAL && inspectInternalMethods
|| rights == AccessRights.PROTECTED && inspectProtectedMethods
|| rights == AccessRights.PRIVATE && inspectPrivateMethods;
return
rights == AccessRights.PUBLIC && inspectPublicMethods ||
rights == AccessRights.INTERNAL && inspectInternalMethods ||
rights == AccessRights.PROTECTED && inspectProtectedMethods ||
rights == AccessRights.PRIVATE && inspectPrivateMethods;
}
}

Expand Down
35 changes: 8 additions & 27 deletions src/Exceptional/Models/ThrownExceptionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,7 @@ public bool IsException(IDeclaredType exceptionType)
{
return false;
}
if (exceptionType == null)
{
return false;
}
return ExceptionType.Equals(exceptionType);
return exceptionType != null && ExceptionType.Equals(exceptionType);
}

/// <summary>Checks whether the thrown exception is the same as <paramref name="exceptionDocumentation" />.</summary>
Expand All @@ -87,11 +83,7 @@ public bool IsExceptionOrSubtype(ExceptionDocCommentModel exceptionDocumentation
{
return false;
}
if (exceptionDocumentation.ExceptionType == null)
{
return false;
}
return ExceptionType.IsSubtypeOf(exceptionDocumentation.ExceptionType);
return exceptionDocumentation.ExceptionType != null && ExceptionType.IsSubtypeOf(exceptionDocumentation.ExceptionType);
}

private void CheckAccessorOverride(IExceptionsOriginModel exceptionsOrigin, IDeclaredType exceptionType)
Expand Down Expand Up @@ -202,10 +194,7 @@ public bool IsExceptionDocumented
{
get
{
if (!_isExceptionDocumented.HasValue)
{
_isExceptionDocumented = IsExceptionDocumentedInternal(IsException);
}
_isExceptionDocumented ??= IsExceptionDocumentedInternal(IsException);
return _isExceptionDocumented.Value;
}
}
Expand All @@ -215,10 +204,7 @@ public bool IsExceptionOrSubtypeDocumented
{
get
{
if (!_isExceptionOrSubtypeDocumented.HasValue)
{
_isExceptionOrSubtypeDocumented = IsExceptionDocumentedInternal(IsExceptionOrSubtype);
}
_isExceptionOrSubtypeDocumented ??= IsExceptionDocumentedInternal(IsExceptionOrSubtype);
return _isExceptionOrSubtypeDocumented.Value;
}
}
Expand All @@ -235,11 +221,9 @@ public bool IsThrownFromAnonymousMethod
{
get
{
if (!_isThrownFromAnonymousMethod.HasValue)
{
var parent = ExceptionsOrigin.Node;
_isThrownFromAnonymousMethod = IsParentAnonymousMethodExpression(parent);
}
if (_isThrownFromAnonymousMethod.HasValue) return _isThrownFromAnonymousMethod.Value;
var parent = ExceptionsOrigin.Node;
_isThrownFromAnonymousMethod = IsParentAnonymousMethodExpression(parent);
return _isThrownFromAnonymousMethod.Value;
}
}
Expand Down Expand Up @@ -293,10 +277,7 @@ private bool IsWrongAccessor
break;
}
}
if (_isWrongAccessor == null)
{
_isWrongAccessor = false;
}
_isWrongAccessor ??= false;
return _isWrongAccessor.Value;
}
}
Expand Down
10 changes: 3 additions & 7 deletions src/Exceptional/Models/ThrownExceptionsReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,13 @@ public static IEnumerable<ThrownExceptionModel> Read(

public static IEnumerable<ThrownExceptionModel> Read(IAnalyzeUnit analyzeUnit, ObjectCreationExpressionModel objectCreationExpression)
{
var declaredElement = objectCreationExpression.Node.ConstructorReference.Resolve().DeclaredElement;
var declaredElement = objectCreationExpression.Node?.ConstructorReference?.Resolve()?.DeclaredElement;
if (declaredElement == null)
{
return Enumerable.Empty<ThrownExceptionModel>();
return [];
}
var xmlDoc = declaredElement.GetXMLDoc(true);
if (xmlDoc == null)
{
return Enumerable.Empty<ThrownExceptionModel>();
}
return Read(analyzeUnit, objectCreationExpression, xmlDoc);
return xmlDoc == null ? [] : Read(analyzeUnit, objectCreationExpression, xmlDoc);
}

private static IEnumerable<ThrownExceptionModel> Read(IAnalyzeUnit analyzeUnit, IExceptionsOriginModel exceptionsOrigin, XmlNode xmlDoc)
Expand Down
18 changes: 18 additions & 0 deletions src/Exceptional/Options/InspectionLevelOptionsPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public InspectionLevelOptionsPage(
CreateCheckboxInspectInternal(lifetime, optionsSettingsSmartContext.StoreOptionsTransactionContext);
CreateCheckboxInspectProtected(lifetime, optionsSettingsSmartContext.StoreOptionsTransactionContext);
CreateCheckboxInspectPrivate(lifetime, optionsSettingsSmartContext.StoreOptionsTransactionContext);
CreateCheckboxInspectConstructors(lifetime, optionsSettingsSmartContext.StoreOptionsTransactionContext);
}

#endregion
Expand Down Expand Up @@ -105,6 +106,23 @@ private void CreateCheckboxInspectPublic(Lifetime lifetime, IContextBoundSetting
AddBoolOption((ExceptionalSettings key) => key.InspectPublicMethods, OptionsLabels.InspectionLevel.InspectPublicMethodsAndProperties);
}

private void CreateCheckboxInspectConstructors(Lifetime lifetime, IContextBoundSettingsStoreLive storeOptionsTransactionContext)
{
IProperty<bool> property = new Property<bool>(lifetime, "Exceptional::InspectionLevel::InspectConstructorsAndProperties");
property.SetValue(storeOptionsTransactionContext.GetValue((ExceptionalSettings key) => key.InspectConstructors));
property.Change.Advise(
lifetime,
a =>
{
if (!a.HasNew)
{
return;
}
storeOptionsTransactionContext.SetValue((ExceptionalSettings key) => key.InspectConstructors, a.New);
});
AddBoolOption((ExceptionalSettings key) => key.InspectConstructors, OptionsLabels.InspectionLevel.InspectConstructorsProperties);
}

#endregion
}
}
1 change: 1 addition & 0 deletions src/Exceptional/Options/OptionsLabels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public static class InspectionLevel
public const string InspectPrivateMethodsAndProperties = "Private methods";
public const string InspectProtectedMethodsAndProperties = "Protected methods";
public const string InspectPublicMethodsAndProperties = "Public methods";
public const string InspectConstructorsProperties = "Constructors";

#endregion
}
Expand Down
4 changes: 2 additions & 2 deletions src/Exceptional/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
[assembly: System.Reflection.AssemblyDescription("Analyzes thrown and documented C# exceptions and suggests improvements.")]
[assembly: System.Reflection.AssemblyProduct("Exceptional")]
[assembly: System.Reflection.AssemblyCompany("Mahmoud Fakhoury")]
[assembly: System.Reflection.AssemblyCopyright("Copyright © 2024 MF")]
[assembly: System.Reflection.AssemblyVersion("2024.3.2")]
[assembly: System.Reflection.AssemblyCopyright("Copyright © 2025 MF")]
[assembly: System.Reflection.AssemblyVersion("2025.2.8")]
[assembly: System.Runtime.InteropServices.ComVisible(false)]
[assembly: System.Runtime.InteropServices.Guid("3628d589-e118-4c2c-bd8e-fdef6b6ed07c")]

Expand Down
Loading

0 comments on commit 83b5624

Please sign in to comment.