Adding properties to a source set using extensions, not conventions

I’m writing some plugins that are supposed to work with the same source set. (This is a similar situation to Java, Groovy and Scala.)

I have a systemverilog plugin that adds its source directory set to a source set. The DSL is modeled after that of the Java plugin:

sourceSets {
    main {
        sv
    }
}

I also have a vhdl plugin that I would like to be able to apply on top of the systemverilog plugin. This would give me the following DSL:

sourceSets {
    main {
        sv {
            // configuration for 'systemverilog'
        }
        vhdl {
            // configuration for 'vhdl'
        }
    }
}

Currently, I have a SourceSet defined in systemverilog plugin, which contains both languages:

public interface SourceSet extends Named, ExtensionAware {
    SourceDirectorySet getSv();
    SourceSet sv(@Nullable Closure configureClosure);
    SourceSet sv(Action<? super SourceDirectorySet> configureAction);

    SourceDirectorySet getVhdl);
    SourceSet vhdl(@Nullable Closure configureClosure);
    SourceSet vhdl(Action<? super SourceDirectorySet> configureAction);
}

I would like the vhdl source to only be available when applying the vhdl plugin.

For inspiration, I had a look at how the Groovy plugin handles its source set. It does this via conventions. I found this issue that states that the plan is to deprecate conventions and to use extensions exclusively.

I’m not sure how I would go about it, though. I tried to split it into two source sets:

public interface SystemVerilogSourceSet extends Named, ExtensionAware {
    SourceDirectorySet getSv();
    SourceSet sv(@Nullable Closure configureClosure);
    SourceSet sv(Action<? super SourceDirectorySet> configureAction);
}

public interface VhdlSourceSet extends Named, ExtensionAware {
    SourceDirectorySet getVhdl);
    SourceSet vhdl(@Nullable Closure configureClosure);
    SourceSet vhdl(Action<? super SourceDirectorySet> configureAction);
}

I thought of using the ext extension to add a new property to the SystemVerilogSourceSet:

final VhdlSourceSet vhdlSourceSet = new DefaultVhdlSourceSet("vhdl", project.getObjects());
// ... configure 'vhdl' source set

SystemVerilogSourceSet svSourceSet = ... // gotten from the `systemverilog` plugin's extension

svSourceSet.getExtensions().getExtraProperties().set("vhdl", vhdlSourceSet);

This created sourceSets.main.vhdl, but that is of type VhdlSourceSet, not SourceDirectorySet (as sourceSets.main.sv is).

I went back and created a new class for the extension that implements SourceDirectorySet:

public class VhdlSourceSetExtension implements SourceDirectorySet {
    private final VhdlSourceSet sourceSet; // gotten from constructor
    // ... adapted to 'SourceDirectorySet'
}

I added an instance of this class as the vhdl property:

VhdlSourceSetExtension vhdlSourceSetExtension = new VhdlSourceSetExtension(vhdlSourceSet);
svSourceSet.getExtensions().getExtraProperties().set("vhdl", vhdlSourceSetExtension);

Now sourceSets.main.vhdl is of the correct type. I can, for example, do stuff like println sourceSets.main.vhdl.files.

What I can’t do is configure vhdl using a closure. The following doesn’t work:

sourceSets {
    main {
        vhdl {
            exclude("**/dummy.vhd")
        }
    }
}

This part of the DSL was handled by the SourceSet vhdl(@Nullable Closure configureClosure) function. I have no idea how to add this to the SystemVerilogSourceSet.

It would be really helpful if someone from the Core Dev team would share some of their ideas for replacing source set conventions with extensions in the JVM plugins. Will the DSL stay exactly the same? Can it or does moving to extensions mean changing the DSL as well?