11using Semmle . Extraction . CSharp ;
22using Semmle . Util . Logging ;
33using Semmle . Autobuild . Shared ;
4+ using Semmle . Util ;
5+ using System . Linq ;
46
57namespace Semmle . Autobuild . CSharp
68{
@@ -29,6 +31,8 @@ public CSharpAutobuildOptions(IBuildActions actions) : base(actions)
2931
3032 public class CSharpAutobuilder : Autobuilder < CSharpAutobuildOptions >
3133 {
34+ private BuildCommandAutoRule ? buildCommandAutoRule ;
35+
3236 public CSharpAutobuilder ( IBuildActions actions , CSharpAutobuildOptions options ) : base ( actions , options ) { }
3337
3438 public override BuildScript GetBuildScript ( )
@@ -99,13 +103,15 @@ BuildScript IntermediateAttempt(BuildScript s) =>
99103 ( s & CheckExtractorRun ( false ) ) |
100104 ( attemptExtractorCleanup & BuildScript . Failure ) ;
101105
106+ this . buildCommandAutoRule = new BuildCommandAutoRule ( DotNetRule . WithDotNet ) ;
107+
102108 attempt =
103109 // First try .NET Core
104110 IntermediateAttempt ( new DotNetRule ( ) . Analyse ( this , true ) ) |
105111 // Then MSBuild
106112 ( ( ) => IntermediateAttempt ( new MsBuildRule ( ) . Analyse ( this , true ) ) ) |
107113 // And finally look for a script that might be a build script
108- ( ( ) => new BuildCommandAutoRule ( DotNetRule . WithDotNet ) . Analyse ( this , true ) & CheckExtractorRun ( true ) ) |
114+ ( ( ) => this . buildCommandAutoRule . Analyse ( this , true ) & CheckExtractorRun ( true ) ) |
109115 // All attempts failed: print message
110116 AutobuildFailure ( ) ;
111117 break ;
@@ -114,6 +120,54 @@ BuildScript IntermediateAttempt(BuildScript s) =>
114120 return attempt ;
115121 }
116122
123+ protected override void AutobuildFailureDiagnostic ( )
124+ {
125+ DiagnosticMessage message ;
126+
127+ // if `ScriptPath` is not null here, the `BuildCommandAuto` rule was
128+ // run and found at least one script to execute
129+ if ( this . buildCommandAutoRule is not null &&
130+ this . buildCommandAutoRule . ScriptPath is not null )
131+ {
132+ // if we found multiple build scripts in the project directory, then we can say
133+ // as much to indicate that we may have picked the wrong one;
134+ // otherwise, we just report that the one script we found didn't work
135+ if ( this . buildCommandAutoRule . CandidatePaths . Count ( ) > 1 )
136+ {
137+ var source = GetDiagnosticSource ( "multiple-build-scripts" , "There are multiple potential build scripts" ) ;
138+ message = new DiagnosticMessage ( source )
139+ {
140+ MarkdownMessage =
141+ "We found multiple potential build scripts for your project and " +
142+ $ "attempted to run `{ buildCommandAutoRule . ScriptPath } `, which failed. " +
143+ "This may not be the right build script for your project. " +
144+ "You can specify which build script to use by providing a suitable build command for your project."
145+ } ;
146+ }
147+ else
148+ {
149+ var source = GetDiagnosticSource ( "script-failure" , "Unable to build project using build script" ) ;
150+ message = new DiagnosticMessage ( source )
151+ {
152+ MarkdownMessage =
153+ "We attempted to build your project using a script located at " +
154+ $ "`{ buildCommandAutoRule . ScriptPath } `, which failed. " +
155+ "You can manually specify a suitable build command for your project."
156+ } ;
157+ }
158+ }
159+ else
160+ {
161+ // none of the above apply; produce a generic autobuild failure message
162+ base . AutobuildFailureDiagnostic ( ) ;
163+ return ;
164+ }
165+
166+ // all messages generated here are errors
167+ message . Severity = DiagnosticMessage . TspSeverity . Error ;
168+ Diagnostic ( message ) ;
169+ }
170+
117171 /// <summary>
118172 /// Gets the build strategy that the autobuilder should apply, based on the
119173 /// options in the `lgtm.yml` file.
0 commit comments