11using System ;
2+ using System . Collections . Generic ;
23using System . Linq ;
34using System . Text . RegularExpressions ;
45using Semmle . Autobuild . Shared ;
@@ -56,6 +57,70 @@ public override void Fire(DiagnosticClassifier classifier, Match match)
5657 }
5758 }
5859
60+ public class MissingProjectFileRule : DiagnosticRule
61+ {
62+ private const string runsOnDocsUrl = "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on" ;
63+ private const string checkoutDocsUrl = "https://github.com/actions/checkout#usage" ;
64+
65+ public class Result : IDiagnosticsResult
66+ {
67+ /// <summary>
68+ /// A set of missing project files.
69+ /// </summary>
70+ public HashSet < string > MissingProjectFiles { get ; }
71+
72+ public Result ( )
73+ {
74+ this . MissingProjectFiles = new HashSet < string > ( ) ;
75+ }
76+
77+ public DiagnosticMessage ToDiagnosticMessage < T > ( Autobuilder < T > builder ) where T : AutobuildOptionsShared
78+ {
79+ var diag = builder . MakeDiagnostic (
80+ $ "missing-project-files",
81+ $ "Missing project files"
82+ ) ;
83+ diag . MarkdownMessage =
84+ "Some project files were not found when CodeQL built your project:\n \n " +
85+ this . MissingProjectFiles . AsEnumerable ( ) . ToMarkdownList ( MarkdownUtil . CodeFormatter , 5 ) +
86+ "\n \n This may lead to subsequent failures. " +
87+ "You can check for common causes for missing project files:\n \n " +
88+ $ "- Ensure that the project is built using the { runsOnDocsUrl . ToMarkdownLink ( "intended operating system" ) } and that filenames on case-sensitive platforms are correctly specified.\n " +
89+ $ "- If your repository uses Git submodules, ensure that those are { checkoutDocsUrl . ToMarkdownLink ( "checked out" ) } before the CodeQL action is run.\n " +
90+ "- If you auto-generate some project files as part of your build process, ensure that these are generated before the CodeQL action is run." ;
91+ diag . Severity = DiagnosticMessage . TspSeverity . Warning ;
92+
93+ return diag ;
94+ }
95+ }
96+
97+ public MissingProjectFileRule ( ) :
98+ base ( "MSB3202: The project file \" (?<projectFile>[^\" ]+)\" was not found. \\ [(?<location>[^\\ ]]+)\\ ]" )
99+ {
100+ }
101+
102+ public override void Fire ( DiagnosticClassifier classifier , Match match )
103+ {
104+ if ( ! match . Groups . TryGetValue ( "projectFile" , out var projectFile ) )
105+ throw new ArgumentException ( "Expected regular expression match to contain projectFile" ) ;
106+ if ( ! match . Groups . TryGetValue ( "location" , out var location ) )
107+ throw new ArgumentException ( "Expected regular expression match to contain location" ) ;
108+
109+ var result = classifier . Results . OfType < Result > ( ) . FirstOrDefault ( ) ;
110+
111+ // if we do not yet have a result for this rule, create one and add it to the list
112+ // of results the classifier knows about
113+ if ( result is null )
114+ {
115+ result = new Result ( ) ;
116+ classifier . Results . Add ( result ) ;
117+ }
118+
119+ // then add the missing project file
120+ result . MissingProjectFiles . Add ( projectFile . Value ) ;
121+ }
122+ }
123+
59124 /// <summary>
60125 /// Implements a <see cref="DiagnosticClassifier" /> which applies C#-specific rules to
61126 /// the build output.
@@ -66,6 +131,7 @@ public CSharpDiagnosticClassifier()
66131 {
67132 // add C#-specific rules to this classifier
68133 this . AddRule ( new MissingXamarinSdkRule ( ) ) ;
134+ this . AddRule ( new MissingProjectFileRule ( ) ) ;
69135 }
70136 }
71137}
0 commit comments