Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

C# support foundations #161

Merged
merged 2 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pkg/cli/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
execunit "github.com/klothoplatform/klotho/pkg/exec_unit"
"github.com/klothoplatform/klotho/pkg/infra/kubernetes"
"github.com/klothoplatform/klotho/pkg/infra/pulumi_aws"
"github.com/klothoplatform/klotho/pkg/lang/csharp"
csRuntimes "github.com/klothoplatform/klotho/pkg/lang/csharp/runtimes"
"github.com/klothoplatform/klotho/pkg/lang/golang"
goRuntimes "github.com/klothoplatform/klotho/pkg/lang/golang/runtimes"
"github.com/klothoplatform/klotho/pkg/lang/javascript"
Expand Down Expand Up @@ -51,6 +53,7 @@ func (b *PluginSetBuilder) AddAll() error {
b.AddJavascript,
b.AddPython,
b.AddGo,
b.AddCSharp,
b.AddPulumi,
b.AddPostCompilation,
} {
Expand Down Expand Up @@ -113,6 +116,15 @@ func (b *PluginSetBuilder) AddGo() error {
return nil
}

func (b *PluginSetBuilder) AddCSharp() error {
csRuntime, err := csRuntimes.GetRuntime(b.Cfg)
if err != nil {
return err
}
b.Transform = append(b.Transform, csharp.NewCSharpPlugins(b.Cfg, csRuntime))
return nil
}

func (b *PluginSetBuilder) setupProvider() (err error) {
if b.provider != nil {
return nil
Expand Down
15 changes: 13 additions & 2 deletions pkg/input/readdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package input

import (
"encoding/json"
"fmt"
"io"
"io/fs"
"os"
Expand All @@ -10,6 +11,7 @@ import (

"github.com/klothoplatform/klotho/pkg/config"
"github.com/klothoplatform/klotho/pkg/core"
"github.com/klothoplatform/klotho/pkg/lang/csharp"
"github.com/klothoplatform/klotho/pkg/lang/dockerfile"
"github.com/klothoplatform/klotho/pkg/lang/golang"
"github.com/klothoplatform/klotho/pkg/lang/javascript"
Expand Down Expand Up @@ -45,6 +47,7 @@ const (
JavaScript languageName = "JavaScript"
Python languageName = "Python"
Go languageName = "Go"
CSharp languageName = "C#"
Yaml languageName = "Yaml"
DockerFile languageName = "Dockerfile"
)
Expand Down Expand Up @@ -110,6 +113,13 @@ func ReadDir(fsys fs.FS, cfg config.Application, cfgFilePath string) (*core.Inpu
jsLang := &languageFiles{name: JavaScript, packageFileName: "package.json", packageFileOpener: Upcast(javascript.NewPackageFile)}
pyLang := &languageFiles{name: Python, packageFileName: "requirements.txt", packageFileOpener: Upcast(python.NewRequirementsTxt)}
goLang := &languageFiles{name: Go, packageFileName: "go.mod", packageFileOpener: Upcast(golang.NewGoMod)}
csLang := &languageFiles{
name: CSharp,
// TODO: Since C# projects don't have a specific named project file, we'll need to update how looking for the project file works.
packageFileName: fmt.Sprintf("%s.csproj", cfg.AppName),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this definitely needs a better implementation.

// TODO: package files in C# are currently unused, so no need to open & parse them.
packageFileOpener: func(path string, content io.Reader) (f core.File, err error) { return &core.FileRef{FPath: path}, nil },
}
yamlLang := &languageFiles{name: Yaml}
dockerfileLang := &languageFiles{name: DockerFile}
allLangs := []*languageFiles{jsLang, pyLang, goLang, yamlLang}
Expand Down Expand Up @@ -180,13 +190,14 @@ func ReadDir(fsys fs.FS, cfg config.Application, cfgFilePath string) (*core.Inpu
f, err = addFile(fsys, path, relPath, javascript.NewFile)
jsLang.foundSources = true
case ".py":
// TODO we may need to do something similar to the js stuff above
f, err = addFile(fsys, path, relPath, python.NewFile)
pyLang.foundSources = true
case ".go":
// TODO we may need to do something similar to the js stuff above
f, err = addFile(fsys, path, relPath, golang.NewFile)
goLang.foundSources = true
case ".cs":
f, err = addFile(fsys, path, relPath, csharp.NewFile)
csLang.foundSources = true
case ".yaml", ".yml":
if path == cfgFilePath {
return nil
Expand Down
50 changes: 50 additions & 0 deletions pkg/lang/csharp/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package csharp

import (
"io"
"regexp"
"strings"

"github.com/klothoplatform/klotho/pkg/core"
"github.com/klothoplatform/klotho/pkg/lang"
"github.com/smacker/go-tree-sitter/csharp"
)

var multilineCommentMarginRegexp = regexp.MustCompile(`(?m)^\s*[*]*[ \t]*`) // we need to use [ \t] instead of \s, because \s includes newlines in (?m) mode.

var Language = core.SourceLanguage{
ID: core.LanguageId("csharp"),
Sitter: csharp.GetLanguage(),
CapabilityFinder: lang.NewCapabilityFinder("comment", lang.CompositePreprocessor(
lang.RegexpRemovePreprocessor(`//\s*`),
func(comment string) string {
// Check for comments starting with `/*`.
// If you don't find one, just return this comment unchanged.
// If you do find one, snip off the start and end chars, as well as any `*`s that prefix a line
// (this is a common style for giving the comment a left border).
if !strings.HasPrefix(comment, "/*") {
return comment
}
// The comment is something like:
// /** foo
// * bar
// */
//
// First, we'll trim the opening and closing slashes, to get it to:
// ** foo
// * bar
// *
//
// Then, we'll use a regexp to remove an opening stretch of `*`s from each line
comment = comment[1 : len(comment)-1]
comment = multilineCommentMarginRegexp.ReplaceAllString(comment, "")
// `/*`-style comments never combine with subsequent comments
return comment
},
)),
TurnIntoComment: lang.MakeLineCommenter("// "),
}

func NewFile(path string, content io.Reader) (f *core.SourceFile, err error) {
return core.NewSourceFile(path, content, Language)
}
35 changes: 35 additions & 0 deletions pkg/lang/csharp/plugins.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package csharp

import (
"github.com/klothoplatform/klotho/pkg/config"
"github.com/klothoplatform/klotho/pkg/core"
"go.uber.org/zap"
)

type (
CSharpPlugins struct {
Plugins []core.Plugin
}
)

func NewCSharpPlugins(cfg *config.Application, runtime Runtime) *CSharpPlugins {
return &CSharpPlugins{
Plugins: []core.Plugin{},
}
}

func (c CSharpPlugins) Name() string { return "C#" }

func (c CSharpPlugins) Transform(result *core.CompilationResult, deps *core.Dependencies) error {
for _, p := range c.Plugins {
log := zap.L().With(zap.String("plugin", p.Name()))
log.Debug("starting")
err := p.Transform(result, deps)
if err != nil {
return core.NewPluginError(p.Name(), err)
}
log.Debug("completed")
}

return nil
}
11 changes: 11 additions & 0 deletions pkg/lang/csharp/queries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package csharp

import (
"github.com/klothoplatform/klotho/pkg/query"
sitter "github.com/smacker/go-tree-sitter"
)

// DoQuery is a thin wrapper around `query.Exec` to use C# as the Language.
func DoQuery(c *sitter.Node, q string) query.NextMatchFunc {
return query.Exec(Language, c, q)
}
6 changes: 6 additions & 0 deletions pkg/lang/csharp/runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package csharp

type (
Runtime interface {
}
)
11 changes: 11 additions & 0 deletions pkg/lang/csharp/runtimes/aws/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package aws_runtime

import (
"github.com/klothoplatform/klotho/pkg/config"
"github.com/klothoplatform/klotho/pkg/provider/aws"
)

type AwsRuntime struct {
TemplateConfig aws.TemplateConfig
Cfg *config.Application
}
31 changes: 31 additions & 0 deletions pkg/lang/csharp/runtimes/runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package runtimes

import (
"fmt"

"github.com/klothoplatform/klotho/pkg/config"
"github.com/klothoplatform/klotho/pkg/lang/csharp"
aws_runtime "github.com/klothoplatform/klotho/pkg/lang/csharp/runtimes/aws"
"github.com/klothoplatform/klotho/pkg/provider"
"github.com/klothoplatform/klotho/pkg/provider/aws"
)

func GetRuntime(cfg *config.Application) (csharp.Runtime, error) {
switch cfg.Provider {
case "gcp", "azure":
// TODO GCP and Azure is hacked to be the same as AWS so we can generate a topology diagram, but the compilation won't work.
fallthrough
case "aws":
return &aws_runtime.AwsRuntime{
Cfg: cfg,
TemplateConfig: aws.TemplateConfig{
TemplateConfig: provider.TemplateConfig{
AppName: cfg.AppName,
},
PayloadsBucketName: aws.SanitizeS3BucketName(cfg.AppName),
},
}, nil
}

return nil, fmt.Errorf("could not get C# runtime for provider: %v", cfg.Provider)
}