Draco-lang / Language-suggestions

Collecting ideas for a new .NET language that could replace C#
75 stars 5 forks source link

Summary on project file formats #75

Closed Binto86 closed 1 year ago

Binto86 commented 2 years ago

In this issue i will look at existing project file formats used by different languages. I will use sample .NET project file translated to these formats.

Template

## Format Name
Link to Documentation
Sample Project File

Investigated Formats

If i have missed any formats, then let me know in the comments and i will add it.

XML

https://docs.fileformat.com/web/xml/

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Foo\Foo.csproj" />
  </ItemGroup>

</Project>

Json

https://docs.fileformat.com/web/json/

{
  "Project":{
    "Sdk":"Microsoft.NET.Sdk",
    "PropertyGroup":{
        "TargetFramework":"net6.0"
    },
    "ItemGroup":{
        "PackageReference":[
            {"Include":"Newtonsoft.Json", "Version":"13.0.1" }
        ],
        "ProjectReference":[
            {"Include":"..\\Foo\\Foo.csproj"}
        ]
    }
  }
}

Json5

https://spec.json5.org/

{
  sdk: "Microsoft.NET.Sdk",
  targetFramework: "net6.0",
  packageReference: [
  {
    Name: "Newtonsoft.Json",
    Version: "13.0.1"
    // JSON5 allow comments, so it 's not an issue.
  }],
  projectReference: [
    "..\\Foo\\Foo.csproj"
  ]
}

Toml

https://docs.fileformat.com/programming/toml/

[Project]
    Sdk="Microsoft.NET.Sdk"
    [Project.PropertyGroup]
        TargetFramework="net6.0"
    [Project.ItemGroup]
        [Project.ItemGroup.PackageReference]
            Include="Newtonsoft.Json" 
            Version="13.0.1" 
    [Project.ItemGroup]
        [Project.ItemGroup.ProjectReference]
            Include="..\\Foo\\Foo.csproj" 

Edited Toml structure

Name = "My project"
Sdk = "Microsoft.NET.Sdk"

[properties]
TargetFramework = "net6.0"

[dependencies]
"Newtonsoft.Json" = {Name= "Newtonsoft.Json", Version= "13.0.1" }
#"Newtonsoft.Json" = { Version= "13.0.1" } is also valid, becaue the name and the alias are the same
Foo = { Path = "..\\Foo\\Foo.csproj" } 

Yaml

https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

project:
  - sdk: Microsoft.Net.Sdk
  - propertyGroup:
    - targetFramework: net6.0
  - itemGroup:
    - packageReference:
        include: Newtonsoft.Json
        version: 13.0.1
    - projectReference:
        include: ../Foo/Foo.csproj
  # this is comment
jl0pd commented 2 years ago

Microsoft have tried to use json for some time, but then returned back to xml, because everything in ecosystem uses this. Using other file format will make it harder (if not impossible) to use it with MSBuild and tooling built around it

LPeter1997 commented 2 years ago

I personally edit my projectfile by hand a lot, and XML makes it kind of hard. JSON is only a small improvement on that, it is too a bit cumbersome because of the many-many quotes. My personal favorite so far was Rust with its TOML files, so my initial choice would be that.

Microsoft have tried to use json for some time, but then returned back to xml, because everything in ecosystem uses this. Using other file format will make it harder (if not impossible) to use it with MSBuild and tooling built around it

That's entirely true, but I wonder if translating the TOML to a project XML or even to an MSBuild file straight away would be beneficial to us and solve the issue. We definitely should utilize MSBuild, we shouldn't cut ourselves off from that.

Kuinox commented 2 years ago

Personally, I like JSON5 configs.
It's difficult to do something more concise without being whitespace dependent. Everyone know json, (which is my issue with toml, not everyone know TOML).

While we will probably use msbuild, I dont think we have to follow the csproj format.
I like a bit(excluding lack of comment, etc) the node package.json format.
An exemple of what it could look like:

{
  sdk: "Microsoft.NET.Sdk",
  targetFramework: "net6.0",
  packageReference: {
    "Newtonsoft.Json": "13.0.1",
    // JSON5 allow comments, so it 's not an issue.
    "SpecialDependecy": {
       version: "1.2.3",
       someAttribute: true
    }
  },
  projectReference: [
    "..\\Foo\\Foo.csproj"
  ]
}

Then adding a way for real msbuild extensibility.

jl0pd commented 2 years ago

Yaml gives best signal-to-noise ratio

project:
  - sdk: Microsoft.Net.Sdk
  - propertyGroup:
    - targetFramework: net6.0
  - itemGroup:
    - packageReference:
        include: Newtonsoft.Json
        version: 13.0.1
  # this is comment
  - itemGroup:
    - projectReference:
        include: ../Foo/Foo.csproj

Unfortunately each section must be preceded with minus -, otherwise parsers complain about duplicating property itemGroup

LPeter1997 commented 2 years ago

IMO the flattest and neatest would be TOML with a changed structure:

name = "My project"
sdk = "Microsoft.NET.Sdk"

[properties]
target_framework = "net6.0"

[dependencies]
json = { name = "Newtonsoft.Json", version = "13.0.1" }
foo = { path = "..\\Foo\\Foo.csproj" } 

No unnecessary indentation and most are already familiar with INI files.

Binto86 commented 2 years ago

Added Json5, Yaml and new format for Toml

reflectronic commented 1 year ago

I wonder if translating the TOML to a project XML or even to an MSBuild file straight away would be beneficial to us and solve the issue.

It would make it impossible to easily use the dotnet CLI to build, run, and test applications. It also adds a lot of complexity to tools, especially ones that are intrinsically MSBuild-based (e.g. support for the VS project system), but also generally, since tools need to understand the build environment (e.g. a language server needs to see the project's dependencies).

I would really strongly suggest sticking with MSBuild XML all the way through. For better or for worse, it is what .NET has standardized on. It is the only way to ensure that, at the very least, the dotnet CLI works excellently with Draco, from dotnet new to dotnet build/dotnet test to dotnet publish. It also opens the door to better tooling in the future.

There are a number of projects that do a similar thing. Here is how IKVM.NET does it:

<Project Sdk="IKVM.NET.Sdk/8.3.0" />

    <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <OutputType>Exe</OutputType>
    </PropertyGroup>

</Project>

You just add your .java files to the project folder and dotnet build will run the Java compiler and their Java→CIL translator, no external tools required.

The quasi-official IL SDK works in a similar way.

Kuinox commented 1 year ago

Since writting my previous message, I realised my biggest issues with MSBuild is the lack of tooling support: No Intellisense, logs need to be specifically enabled, opened in another app, etc.

Nothing unfixable.