Cake: Unable to use custom static classes with extension methods in cake scripts

Created on 17 Oct 2016  路  8Comments  路  Source: cake-build/cake

What You Are Seeing?

I have added a static class containing extension methods for the AssemblyInforParseResult class in order to simplify the instantiation of an AssemblyInfoSettings object. When running the build, I get the following message:

Error: M:/Projects/Dev/CakeTest/common.cake(34,40): error CS1109: Extension methods must be defined in a top level static class; VersioningHelper is a nested class

What is Expected?

I would expect the build script to be compiled without errors.
I am guessing this happens because Cake converts the entire cake.build into a single class that is then complied with Roslyn, thus my custom class turns into a nested class, and, correctly, the compiler doesn't allow declaring extension methods in it. I am able to circumvent this by creating a class library with the custom functionality and referencing it, but this is not very convenient as the cake script is no longer self-contained.

What version of Cake are you using? Are you running on a 32 or 64 bit system? What environment are you running on? Windows? Linux? Mac? Are you running on a CI Server? If so, which one?

I am running Cake 0.16.2 on Windows (64bit), both locally and on (on-premise) TFS.

How Did You Get This To Happen? (Steps to Reproduce)

Add a static class containing extension methods to a cake script

Output Log

Module directory does not exist.
Analyzing build script...
Analyzing M:/Projects/Dev/CakeTest/build.cake...
Analyzing M:/Projects/Dev/CakeTest/common.cake...
Processing build script...
Installing addins...
Package Cake.FileHelpers has already been installed.
The addin Cake.FileHelpers will reference Cake.FileHelpers.dll.
Creating script session...
Adding reference to mscorlib.dll...
Adding reference to System.dll...
Adding reference to System.Core.dll...
Adding reference to System.Data.dll...
Adding reference to System.Xml.dll...
Adding reference to System.Xml.Linq.dll...
Adding reference to Cake.Core.dll...
Adding reference to Cake.Common.dll...
Adding reference to Cake.exe...
Adding reference to Cake.FileHelpers.dll...
Importing namespace Cake.Common...
Importing namespace Cake.Common.Build...
Importing namespace Cake.Common.Build.AppVeyor...
Importing namespace Cake.Common.Build.AppVeyor.Data...
Importing namespace Cake.Common.Build.BitbucketPipelines...
Importing namespace Cake.Common.Build.BitbucketPipelines.Data...
Importing namespace Cake.Common.Build.Bitrise...
Importing namespace Cake.Common.Build.Bitrise.Data...
Importing namespace Cake.Common.Build.ContinuaCI...
Importing namespace Cake.Common.Build.ContinuaCI.Data...
Importing namespace Cake.Common.Build.Jenkins...
Importing namespace Cake.Common.Build.Jenkins.Data...
Importing namespace Cake.Common.Build.TravisCI...
Importing namespace Cake.Common.Build.TravisCI.Data...
Importing namespace Cake.Common.Diagnostics...
Importing namespace Cake.Common.IO...
Importing namespace Cake.Common.IO.Paths...
Importing namespace Cake.Common.Net...
Importing namespace Cake.Common.Security...
Importing namespace Cake.Common.Solution...
Importing namespace Cake.Common.Solution.Project...
Importing namespace Cake.Common.Solution.Project.Properties...
Importing namespace Cake.Common.Solution.Project.XmlDoc...
Importing namespace Cake.Common.Text...
Importing namespace Cake.Common.Tools...
Importing namespace Cake.Common.Tools.Cake...
Importing namespace Cake.Common.Tools.Chocolatey...
Importing namespace Cake.Common.Tools.Chocolatey.ApiKey...
Importing namespace Cake.Common.Tools.Chocolatey.Config...
Importing namespace Cake.Common.Tools.Chocolatey.Features...
Importing namespace Cake.Common.Tools.Chocolatey.Install...
Importing namespace Cake.Common.Tools.Chocolatey.Pack...
Importing namespace Cake.Common.Tools.Chocolatey.Pin...
Importing namespace Cake.Common.Tools.Chocolatey.Push...
Importing namespace Cake.Common.Tools.Chocolatey.Sources...
Importing namespace Cake.Common.Tools.Chocolatey.Upgrade...
Importing namespace Cake.Common.Tools.DNU...
Importing namespace Cake.Common.Tools.DNU.Build...
Importing namespace Cake.Common.Tools.DNU.Pack...
Importing namespace Cake.Common.Tools.DNU.Restore...
Importing namespace Cake.Common.Tools.DotCover...
Importing namespace Cake.Common.Tools.DotCover.Analyse...
Importing namespace Cake.Common.Tools.DotCover.Cover...
Importing namespace Cake.Common.Tools.DotNetCore...
Importing namespace Cake.Common.Tools.DotNetCore.Build...
Importing namespace Cake.Common.Tools.DotNetCore.Execute...
Importing namespace Cake.Common.Tools.DotNetCore.Pack...
Importing namespace Cake.Common.Tools.DotNetCore.Publish...
Importing namespace Cake.Common.Tools.DotNetCore.Restore...
Importing namespace Cake.Common.Tools.DotNetCore.Run...
Importing namespace Cake.Common.Tools.DotNetCore.Test...
Importing namespace Cake.Common.Tools.DupFinder...
Importing namespace Cake.Common.Tools.Fixie...
Importing namespace Cake.Common.Tools.GitLink...
Importing namespace Cake.Common.Tools.GitReleaseManager...
Importing namespace Cake.Common.Tools.GitReleaseManager.AddAssets...
Importing namespace Cake.Common.Tools.GitReleaseManager.Close...
Importing namespace Cake.Common.Tools.GitReleaseManager.Create...
Importing namespace Cake.Common.Tools.GitReleaseManager.Export...
Importing namespace Cake.Common.Tools.GitReleaseManager.Publish...
Importing namespace Cake.Common.Tools.GitReleaseNotes...
Importing namespace Cake.Common.Tools.GitVersion...
Importing namespace Cake.Common.Tools.ILMerge...
Importing namespace Cake.Common.Tools.ILRepack...
Importing namespace Cake.Common.Tools.InspectCode...
Importing namespace Cake.Common.Tools.MSBuild...
Importing namespace Cake.Common.Tools.MSTest...
Importing namespace Cake.Common.Tools.NSIS...
Importing namespace Cake.Common.Tools.NuGet...
Importing namespace Cake.Common.Tools.NuGet.Install...
Importing namespace Cake.Common.Tools.NuGet.Pack...
Importing namespace Cake.Common.Tools.NuGet.Push...
Importing namespace Cake.Common.Tools.NuGet.Restore...
Importing namespace Cake.Common.Tools.NuGet.SetApiKey...
Importing namespace Cake.Common.Tools.NuGet.SetProxy...
Importing namespace Cake.Common.Tools.NuGet.Sources...
Importing namespace Cake.Common.Tools.NuGet.Update...
Importing namespace Cake.Common.Tools.NUnit...
Importing namespace Cake.Common.Tools.OctopusDeploy...
Importing namespace Cake.Common.Tools.OpenCover...
Importing namespace Cake.Common.Tools.ReportGenerator...
Importing namespace Cake.Common.Tools.ReportUnit...
Importing namespace Cake.Common.Tools.Roundhouse...
Importing namespace Cake.Common.Tools.SignTool...
Importing namespace Cake.Common.Tools.SpecFlow...
Importing namespace Cake.Common.Tools.SpecFlow.StepDefinitionReport...
Importing namespace Cake.Common.Tools.SpecFlow.TestExecutionReport...
Importing namespace Cake.Common.Tools.TextTransform...
Importing namespace Cake.Common.Tools.VSTest...
Importing namespace Cake.Common.Tools.WiX...
Importing namespace Cake.Common.Tools.WiX.Heat...
Importing namespace Cake.Common.Tools.XBuild...
Importing namespace Cake.Common.Tools.XUnit...
Importing namespace Cake.Common.Xml...
Importing namespace Cake.Core...
Importing namespace Cake.Core.Diagnostics...
Importing namespace Cake.Core.IO...
Importing namespace Cake.Core.Scripting...
Importing namespace Cake.FileHelpers...
Importing namespace System...
Importing namespace System.Collections.Generic...
Importing namespace System.IO...
Importing namespace System.Linq...
Importing namespace System.Text...
Importing namespace System.Threading.Tasks...
Compiling build script...
Error: Roslyn.Compilers.CompilationErrorException: M:/Projects/Dev/CakeTest/common.cake(34,40): error CS1109: Extension methods must be defined in a top level static class; VersioningHelper is a nested class
   at Roslyn.Scripting.CommonScriptEngine.CompilationError(DiagnosticBag localDiagnostics, DiagnosticBag diagnostics)
   at Roslyn.Scripting.CommonScriptEngine.Compile(String code, String path, DiagnosticBag diagnostics, Session session, Type delegateType, Type returnType, CancellationToken cancellationToken, Boolean isInteractive, Boolean isExecute, CommonCompilation& compilation, Delegate& factory)
   at Roslyn.Scripting.CommonScriptEngine.Execute[T](String code, String path, DiagnosticBag diagnostics, Session session, Boolean isInteractive)
   at Roslyn.Scripting.Session.Execute(String code)
   at Cake.Core.Scripting.ScriptRunner.Run(IScriptHost host, FilePath scriptPath, IDictionary`2 arguments)
   at Cake.Commands.BuildCommand.Execute(CakeOptions options)
   at Cake.CakeApplication.Run(CakeOptions options)
   at Cake.Program.Main()
Help wanted Improvement Up-for-grabs

Most helpful comment

Workaround is to just do a static extension method without a surrounding class.

All 8 comments

While this isn't possible with the current implementations, weren't opposed to the idea, this would need to be investigated how to best support static classes. Might be something we postpone until we unified around one scripting engine to reduce effort duplication.

Lifting type declarations and methods out of a Roslyn script is actually one of my next blog posts :).

I use a walker on the syntax tree to find stuff that should be lifted: https://github.com/Wyamio/Wyam/blob/9a83529aecef73cfacba849b28f892c251b39748/src/core/Wyam.Configuration/ConfigScript/LiftingWalker.cs Then you create the container class and method and stuff the remainder into it, placing all the stuff you lifted outside.

If there's interest I can take a look at what it would take to apply this approach in Cake. The alternate script host might be problematic though because the approach above obviously only works with Roslyn.

@daveaglick sounds interesting, wonder if it could be done as a WIP module to Cake.

Yes, if it requires Roslyn we can add this as soon as we unify the script engines.

Any progress on this issue?
I have the same problem. Is there some workarounds?

Workaround is to just do a static extension method without a surrounding class.

Thanks, it works!

Repro:

  • build.cake
public static class MyBuildExtensions
{
    public static int ToInt(this string value)
    {
        return Convert.ToInt32(value);
    }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

josemaia picture josemaia  路  4Comments

coxp picture coxp  路  5Comments

thomaslevesque picture thomaslevesque  路  4Comments

johncrim picture johncrim  路  4Comments

vktr picture vktr  路  6Comments