Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
j178 committed Dec 10, 2023
1 parent 595a1bd commit 7ea50ef
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 46 deletions.
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func initCommands() {
rootCmd.SetOut(os.Stdout)
rootCmd.InitDefaultVersionFlag()
rootCmd.Flags().SortFlags = false
rootCmd.PersistentFlags().StringP("lang", "l", "", "language of code to generate: cpp, go, python ...")
rootCmd.PersistentFlags().StringP("lang", "l", "", "language of code to generate: cpp, go, python, java...")
rootCmd.PersistentFlags().StringP("site", "", "", "leetcode site: cn, us")
rootCmd.PersistentFlags().BoolP("yes", "y", false, "answer yes to all prompts")
rootCmd.InitDefaultHelpFlag()
Expand Down
32 changes: 21 additions & 11 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ type Modifier struct {
}

type CodeConfig struct {
Lang string `yaml:"lang" mapstructure:"lang" comment:"Language of code generated for questions: go, python, ... \n(will be override by project config and flag --lang)"`
FilenameTemplate string `yaml:"filename_template" mapstructure:"filename_template" comment:"The default template to generate filename (without extension), e.g. {{.Id}}.{{.Slug}}\nAvailable attributes: Id, Slug, Title, Difficulty, Lang, SlugIsMeaningful\nAvailable functions: lower, upper, trim, padWithZero, toUnderscore, group"`
SeparateDescriptionFile bool `yaml:"separate_description_file" mapstructure:"separate_description_file" comment:"Generate question description into a separate question.md file"`
Blocks []Block `yaml:"blocks,omitempty" mapstructure:"blocks" comment:"Default block definitions for all languages"`
Modifiers []Modifier `yaml:"modifiers,omitempty" mapstructure:"modifiers" comment:"Default modifiers for all languages"`
Go GoConfig `yaml:"go" mapstructure:"go"`
Python PythonConfig `yaml:"python3" mapstructure:"python3"`
Cpp CppConfig `yaml:"cpp" mapstructure:"cpp"`
Rust RustConfig `yaml:"rust" mapstructure:"rust"`
Java BaseLangConfig `yaml:"java" mapstructure:"java"`
Lang string `yaml:"lang" mapstructure:"lang" comment:"Language of code generated for questions: go, python, ... \n(will be override by project config and flag --lang)"`
FilenameTemplate string `yaml:"filename_template" mapstructure:"filename_template" comment:"The default template to generate filename (without extension), e.g. {{.Id}}.{{.Slug}}\nAvailable attributes: Id, Slug, Title, Difficulty, Lang, SlugIsMeaningful\nAvailable functions: lower, upper, trim, padWithZero, toUnderscore, group"`
SeparateDescriptionFile bool `yaml:"separate_description_file" mapstructure:"separate_description_file" comment:"Generate question description into a separate question.md file"`
Blocks []Block `yaml:"blocks,omitempty" mapstructure:"blocks" comment:"Default block definitions for all languages"`
Modifiers []Modifier `yaml:"modifiers,omitempty" mapstructure:"modifiers" comment:"Default modifiers for all languages"`
Go GoConfig `yaml:"go" mapstructure:"go"`
Python PythonConfig `yaml:"python3" mapstructure:"python3"`
Cpp CppConfig `yaml:"cpp" mapstructure:"cpp"`
Rust RustConfig `yaml:"rust" mapstructure:"rust"`
Java JavaConfig `yaml:"java" mapstructure:"java"`
// Add more languages here
}

Expand Down Expand Up @@ -110,6 +110,11 @@ type RustConfig struct {
BaseLangConfig `yaml:",inline" mapstructure:",squash"`
}

type JavaConfig struct {
BaseLangConfig `yaml:",inline" mapstructure:",squash"`
GroupID string `yaml:"group_id" mapstructure:"group_id" comment:"Maven group ID"`
}

type Credentials struct {
From string `yaml:"from" mapstructure:"from" comment:"How to provide credentials: browser, cookies, password or none"`
Browsers []string `yaml:"browsers" mapstructure:"browsers" comment:"Browsers to get cookies from: chrome, safari, edge or firefox. If empty, all browsers will be tried"`
Expand Down Expand Up @@ -223,7 +228,12 @@ func defaultConfig() *Config {
BaseLangConfig: BaseLangConfig{OutDir: "python"},
Executable: constants.DefaultPython,
},
Java: BaseLangConfig{OutDir: "java"},
Java: JavaConfig{
BaseLangConfig: BaseLangConfig{
OutDir: "java",
FilenameTemplate: `p{{ .Id | padWithZero 4 }}{{ if .SlugIsMeaningful }}_{{ .Slug | lower | toUnderscore }}{{ end }}`,
},
},
Rust: RustConfig{BaseLangConfig: BaseLangConfig{OutDir: "rust"}},
// Add more languages here
},
Expand Down
10 changes: 0 additions & 10 deletions lang/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,6 @@ func getTempBinFile(q *leetcode.QuestionData, lang Lang) (string, error) {
return filepath.Join(tmpDir, filename), nil
}

func getTempBinDir(q *leetcode.QuestionData, lang Lang) (string, error) {
tmpDir := config.Get().TempDir()
dirname := fmt.Sprintf("%s-%s", q.TitleSlug, lang.Slug())
dir := filepath.Join(tmpDir, dirname)
if err := utils.CreateIfNotExists(dir, true); err != nil {
return "", err
}
return dir, nil
}

func separateDescriptionFile(lang Lang) bool {
ans := viper.Get("code." + lang.Slug() + ".separate_description_file")
if ans != nil {
Expand Down
12 changes: 6 additions & 6 deletions lang/cpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/j178/leetgo/config"
"github.com/j178/leetgo/constants"
"github.com/j178/leetgo/leetcode"
cppUtils "github.com/j178/leetgo/testutils/cpp"
cppEmbed "github.com/j178/leetgo/testutils/cpp"
"github.com/j178/leetgo/utils"
)

Expand All @@ -19,21 +19,21 @@ type cpp struct {
}

func (c cpp) Initialize(outDir string) error {
headerPath := filepath.Join(outDir, cppUtils.HeaderName)
err := utils.WriteFile(headerPath, cppUtils.HeaderContent)
headerPath := filepath.Join(outDir, cppEmbed.HeaderName)
err := utils.WriteFile(headerPath, cppEmbed.HeaderContent)
if err != nil {
return err
}
stdCxxPath := filepath.Join(outDir, "bits", "stdc++.h")
err = utils.WriteFile(stdCxxPath, cppUtils.StdCxxContent)
err = utils.WriteFile(stdCxxPath, cppEmbed.StdCxxContent)
if err != nil {
return err
}
return nil
}

func (c cpp) HasInitialized(outDir string) (bool, error) {
headerPath := filepath.Join(outDir, cppUtils.HeaderName)
headerPath := filepath.Join(outDir, cppEmbed.HeaderName)
if !utils.IsExist(headerPath) {
return false, nil
}
Expand Down Expand Up @@ -278,7 +278,7 @@ func (c cpp) generateCodeFile(
#include "%s"
using namespace std;
`, cppUtils.HeaderName,
`, cppEmbed.HeaderName,
)
testContent, err := c.generateTestContent(q)
if err != nil {
Expand Down
126 changes: 110 additions & 16 deletions lang/java.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,113 @@ package lang

import (
"fmt"
"path/filepath"
"regexp"
"runtime"
"strings"

"github.com/j178/leetgo/config"
"github.com/j178/leetgo/leetcode"
javaEmbed "github.com/j178/leetgo/testutils/java"
"github.com/j178/leetgo/utils"
)

const (
pomTemplate = `
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>%s</groupId>
<artifactId>%s</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>leetcode-solutions</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.github.j178</groupId>
<artifactId>leetgo-java</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.1</version>
</plugin>
</plugins>
</build>
</project>
`
)

type java struct {
baseLang
}

func mvnwCmd(dir string, args ...string) []string {
cmdName := "mvnw"
if runtime.GOOS == "windows" {
cmdName = "mvnw.cmd"
}
return append([]string{filepath.Join(dir, cmdName), "-q"}, args...)
}

func (j java) HasInitialized(outDir string) (bool, error) {
return false, nil
return utils.IsExist(filepath.Join(outDir, "pom.xml")), nil
}

var nameReplacer = regexp.MustCompile(`[^a-zA-Z0-9_]`)

func (j java) groupID() string {
cfg := config.Get()
if cfg.Code.Java.GroupID != "" {
return cfg.Code.Java.GroupID
}
name := nameReplacer.ReplaceAllString(strings.ToLower(cfg.Author), "_")
return "io.github." + name
}

func (j java) sourceDir() string {
groupID := j.groupID()
path := []string{"src", "main", "java"}
path = append(path, strings.Split(groupID, ".")...)
return filepath.Join(path...)
}

func (j java) Initialize(outDir string) error {
// Copy mvn wrapper from embed
err := utils.CopyFS(outDir, javaEmbed.MvnWrapper)
if err != nil {
return err
}

groupID := j.groupID()
artifactID := "leetcode-solutions"

// Write pom.xml
pomXML := fmt.Sprintf(pomTemplate, groupID, artifactID)
err = utils.WriteFile(filepath.Join(outDir, "pom.xml"), []byte(pomXML))
if err != nil {
return err
}

// Create layout
sourceDir := filepath.Join(outDir, j.sourceDir())
err = utils.MakeDir(sourceDir)
if err != nil {
return err
}
return nil
}

Expand All @@ -32,19 +124,15 @@ func (j java) RunLocalTest(q *leetcode.QuestionData, outDir string, targetCase s
return false, fmt.Errorf("file %s not found", utils.RelToCwd(testFile))
}

execDir, err := getTempBinDir(q, j)
if err != nil {
return false, fmt.Errorf("get temp bin dir failed: %w", err)
}

args := []string{"javac", "-d", execDir, testFile}
err = buildTest(q, genResult, args)
buildCmd := mvnwCmd(outDir, "compile")
err = buildTest(q, genResult, buildCmd)
if err != nil {
return false, fmt.Errorf("build failed: %w", err)
}

args = []string{"java", "--class-path", execDir, "Main"}
return runTest(q, genResult, args, targetCase)
// TODO 生成 package name, 后续执行需要用这个名字拼成的完整 main class
execCmd := mvnwCmd(outDir, "exec:exec", fmt.Sprintf("-Dexec.mainClass=%s.Main"))

Check failure on line 134 in lang/java.go

View workflow job for this annotation

GitHub Actions / lint

printf: fmt.Sprintf format %s reads arg #1, but call has 0 args (govet)
return runTest(q, genResult, execCmd, targetCase)
}

func (j java) generateNormalTestCode(q *leetcode.QuestionData) (string, error) {
Expand All @@ -64,6 +152,7 @@ func (j java) generateTestContent(q *leetcode.QuestionData) (string, error) {

func (j java) generateCodeFile(
q *leetcode.QuestionData,
packageName string,
filename string,
blocks []config.Block,
modifiers []ModifierFunc,
Expand All @@ -72,7 +161,11 @@ func (j java) generateCodeFile(
FileOutput,
error,
) {
codeHeader := ""
codeHeader := fmt.Sprintf(
`package %s;
`,
packageName,
)
testContent, err := j.generateTestContent(q)
if err != nil {
return FileOutput{}, err
Expand Down Expand Up @@ -108,14 +201,14 @@ func (j java) generateCodeFile(

func (j java) GeneratePaths(q *leetcode.QuestionData) (*GenerateResult, error) {
filenameTmpl := getFilenameTemplate(q, j)
baseFilename, err := q.GetFormattedFilename(j.slug, filenameTmpl)
packageName, err := q.GetFormattedFilename(j.slug, filenameTmpl)
if err != nil {
return nil, err
}
genResult := &GenerateResult{
SubDir: baseFilename,
Question: q,
Lang: j,
SubDir: filepath.Join(j.sourceDir(), packageName),
}
genResult.AddFile(
FileOutput{
Expand All @@ -142,14 +235,14 @@ func (j java) GeneratePaths(q *leetcode.QuestionData) (*GenerateResult, error) {

func (j java) Generate(q *leetcode.QuestionData) (*GenerateResult, error) {
filenameTmpl := getFilenameTemplate(q, j)
baseFilename, err := q.GetFormattedFilename(j.slug, filenameTmpl)
packageName, err := q.GetFormattedFilename(j.slug, filenameTmpl)
if err != nil {
return nil, err
}
genResult := &GenerateResult{
Question: q,
Lang: j,
SubDir: baseFilename,
SubDir: filepath.Join(j.sourceDir(), packageName),
}

separateDescriptionFile := separateDescriptionFile(j)
Expand All @@ -158,7 +251,8 @@ func (j java) Generate(q *leetcode.QuestionData) (*GenerateResult, error) {
if err != nil {
return nil, err
}
codeFile, err := j.generateCodeFile(q, "solution.java", blocks, modifiers, separateDescriptionFile)
fqPackageName := fmt.Sprintf("%s.%s", j.groupID(), packageName)
codeFile, err := j.generateCodeFile(q, fqPackageName, "solution.java", blocks, modifiers, separateDescriptionFile)
if err != nil {
return nil, err
}
Expand Down
4 changes: 3 additions & 1 deletion leetcode/question.go
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ func contestShortSlug(contestSlug string) string {
return strings.Replace(contestSlug, "-contest-", "-", 1)
}

var nonIdentifierRe = regexp.MustCompile(`[^a-zA-Z0-9_]`)

func (q *QuestionData) GetFormattedFilename(lang string, filenameTemplate string) (string, error) {
id, slugValid := q.normalizeQuestionId()
data := &filenameTemplateData{
Expand Down Expand Up @@ -595,7 +597,7 @@ func (q *QuestionData) GetFormattedFilename(lang string, filenameTemplate string
return fmt.Sprintf("%0*s", n, s)
},
"toUnderscore": func(s string) string {
return strings.ReplaceAll(s, "-", "_")
return nonIdentifierRe.ReplaceAllString(s, "_")
},
"group": func(size int, s string) string {
id, err := strconv.Atoi(s)
Expand Down
3 changes: 3 additions & 0 deletions testutils/java/.mvn/maven.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-Dmaven.plugin.validation=none
-DskipTests=true
-q
2 changes: 1 addition & 1 deletion testutils/java/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.2/apache-maven-3.9.2-bin.zip
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
4 changes: 4 additions & 0 deletions testutils/java/src/main/java/io/github/j178/abc/A.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.github.j178.abc;

public class A {
}

0 comments on commit 7ea50ef

Please sign in to comment.