-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Roslyn analyzer setup included in Altinn.App.Core to catch configuration errors based on static analysis #651
base: main
Are you sure you want to change the base?
Conversation
9f70ad3
to
685d70a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool...
We should probably make these Errors instead of Warnings unless we find a way to make CI build run with warnings as errors
, because lots of apps has many warnings and these pretty serious issues will just drown.
If we want to deploy this before v9 (I would like to), then we can't make them errors I think. |
I think we can make compile errors in broken apps? |
fbd306b
to
4a882a4
Compare
ec604a7
to
cd1ef91
Compare
This PR is ready for proper review now! Testing infra was as usual not trivial at all, and took the majority of time, but I'm really happy with the result. Another change is using PolySharp to polyfill some stuff such as records. That enabled me to use a pattern that I'm really fond of, especially in places where precise error handling is very important. There is a Callee: https://github.com/Altinn/app-lib-dotnet/pull/651/files#diff-481c24765c42685ba9fdf20ea3d628bbfada6d7c92ccc1e915fb8fed7d8f9269R6-R59 Note that the caller doesn't need a default case in the switch statement, yet all error conditions are propery handled. I also tried to add proper locations to diagnostics by capturing lineinfo from @ivarne re
I think this is a reasonable perspective for sure, but another would be that making those error severity would change build-time behavior. So some apps that are broken now still build, but that changes if we make diagnostics error severity right now. Another approach would be to keep them as warning now, but convert them to errors for v9. Those who want to be strict can turn on |
a2d11a4
to
bfcd9f4
Compare
A new case that popped up - a user had mistakenly created a |
Or even funnier, they could name it |
97b606f
to
b0a5c70
Compare
foreach (var dataType in metadata.DataTypes.Value) | ||
{ | ||
if (dataType.AppLogic.Value is not { } appLogic) | ||
continue; | ||
|
||
var classRef = appLogic.ClassRef; | ||
|
||
var classRefSymbol = context.Compilation.GetTypeByMetadataName(classRef.Value); | ||
|
||
if (classRefSymbol is null) | ||
{ | ||
context.ReportDiagnostic( | ||
Diagnostic.Create( | ||
Diagnostics.ApplicationMetadata.DataTypeClassRefInvalid, | ||
GetLocation(filePath, classRef, sourceText), | ||
classRef.Value, | ||
dataType.Id.Value | ||
) | ||
); | ||
} | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Where Note
implicitly filters its target sequence
foreach (var layoutSet in layoutSets) | ||
{ | ||
if (layoutSet.Id.Value.Equals(showLayout.Value, StringComparison.Ordinal)) | ||
{ | ||
foundLayoutSet = layoutSet; | ||
} | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Where Note
implicitly filters its target sequence
foreach (var dataTypeMetadata in appMetadataContent.Value.DataTypes.Value) | ||
{ | ||
if (dataTypeMetadata.Id.Value.Equals(dataType, StringComparison.Ordinal)) | ||
{ | ||
foundDataTypeInfo = dataTypeMetadata; | ||
} | ||
} |
Check notice
Code scanning / CodeQL
Missed opportunity to use Where Note
implicitly filters its target sequence
catch (Exception ex) | ||
{ | ||
return new ApplicationMetadataParseResult.Error(ex); | ||
} |
Check notice
Code scanning / CodeQL
Generic catch clause Note
catch (Exception ex) | ||
{ | ||
if (ex is OperationCanceledException) | ||
return new ApplicationMetadataResult.Cancelled(); | ||
return new ApplicationMetadataResult.CouldNotReadFile(ex, file); | ||
} |
Check notice
Code scanning / CodeQL
Generic catch clause Note
catch (Exception ex) | ||
{ | ||
if (ex is OperationCanceledException) | ||
return new LayoutSetsResult.Cancelled(); | ||
return new LayoutSetsResult.CouldNotParse(ex, sourceText, file); | ||
} |
Check notice
Code scanning / CodeQL
Generic catch clause Note
catch (Exception ex) | ||
{ | ||
if (ex is OperationCanceledException) | ||
return; | ||
additionalFileAnalysisContext.ReportDiagnostic( | ||
Diagnostic.Create(Diagnostics.UnknownError, Location.None, ex.Message, ex.StackTrace) | ||
); | ||
} |
Check notice
Code scanning / CodeQL
Generic catch clause Note
catch (Exception ex) | ||
{ | ||
if (ex is OperationCanceledException) | ||
return; | ||
compilationAnalysisContext.ReportDiagnostic( | ||
Diagnostic.Create(Diagnostics.UnknownError, Location.None, ex.Message, ex.StackTrace) | ||
); | ||
} |
Check notice
Code scanning / CodeQL
Generic catch clause Note
long v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), | ||
uint v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), | ||
ulong v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), | ||
float v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), |
Check warning
Code scanning / CodeQL
Equality check on floating point values Warning
uint v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), | ||
ulong v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), | ||
float v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), | ||
double v => v == 0 ? 1 : (int)Math.Floor(Math.Log10(v) + 1), |
Check warning
Code scanning / CodeQL
Equality check on floating point values Warning
b0a5c70
to
b8e63bc
Compare
b8e63bc
to
6ccb000
Compare
Quality Gate failedFailed conditions See analysis details on SonarCloud Catch issues before they fail your Quality Gate with our IDE extension SonarLint |
Description
This PR includes a Roslyn analyzer setup that we can use for various things.
To start, this analyzes the
applicationmetadata.json
file and reports errors when it isn't able to resolveclassRef
to its corresponding C# classThe analyzer (and its'
Newtonsoft.Json
dependency) is packaged alongsideAltinn.App.Core
in the analyzers folderI use the
4.1.0
version of the Roslyn libraries for the analyzer. It's supported by almost all of the VS 2022 versions and has been included in the .NET SDK since 6.0 I think.Referencing locally
Related Issue(s)
Verification
Documentation