Skip to content

Commit

Permalink
Reorganize Structure (#13)
Browse files Browse the repository at this point in the history
* move Issue type into internal/lints dir
  • Loading branch information
notJoon authored Jul 19, 2024
1 parent e57cd00 commit df1127d
Show file tree
Hide file tree
Showing 20 changed files with 554 additions and 515 deletions.
58 changes: 29 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ Inspired by Rust's [clippy](https://github.com/rust-lang/rust-clippy), tlin aims
## Installation

- Requirements:
- Go: 1.22 or higher
- latest version of gno
- Go: 1.22 or higher
- latest version of gno

To install tlin CLI, run:

Expand Down Expand Up @@ -74,33 +74,33 @@ func (e *Engine) registerDefaultRules() {

3. (Optional) if your rule requires special formatting, create a new formatter in the `formatter` package:

a. Create a new file (e.g., `formatter/new_rule.go`).
b. Implement the `IssueFormatter` interface for your new rule:

```go
type NewRuleFormatter struct{}

func (f *NewRuleFormatter) Format(
issue internal.Issue,
snippet *internal.SourceCode,
) string {
// Implement formatting logic for new rule here.
}
```

c. Add the new formatter to the `GetFormatter` function in `formatter/fmt.go`.

```go
func GetFormatter(rule string) IssueFormatter {
switch rule {
// ...
case "new_rule": // Add your new rule here
return &NewRuleFormatter{}
default:
return &DefaultFormatter{}
}
}
```
a. Create a new file (e.g., `formatter/new_rule.go`).
b. Implement the `IssueFormatter` interface for your new rule:

```go
type NewRuleFormatter struct{}

func (f *NewRuleFormatter) Format(
issue lints.Issue,
snippet *internal.SourceCode,
) string {
// Implement formatting logic for new rule here.
}
```

c. Add the new formatter to the `GetFormatter` function in `formatter/fmt.go`.

```go
func GetFormatter(rule string) IssueFormatter {
switch rule {
// ...
case "new_rule": // Add your new rule here
return &NewRuleFormatter{}
default:
return &DefaultFormatter{}
}
}
```

By following these steps, you can add new lint rules and ensure they are properly formatted when displayed in the CLI.

Expand Down
13 changes: 7 additions & 6 deletions cmd/tlin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
"sort"

"github.com/gnoswap-labs/lint/formatter"
lint "github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal/lints"
)

func main() {
Expand All @@ -23,13 +24,13 @@ func main() {
}

rootDir := "."
engine, err := lint.NewEngine(rootDir)
engine, err := internal.NewEngine(rootDir)
if err != nil {
fmt.Printf("error initializing lint engine: %v\n", err)
os.Exit(1)
}

var allIssues []lint.Issue
var allIssues []lints.Issue
for _, path := range args {
info, err := os.Stat(path)
if err != nil {
Expand Down Expand Up @@ -69,7 +70,7 @@ func main() {
}
}

issuesByFile := make(map[string][]lint.Issue)
issuesByFile := make(map[string][]lints.Issue)
for _, issue := range allIssues {
issuesByFile[issue.Filename] = append(issuesByFile[issue.Filename], issue)
}
Expand All @@ -82,7 +83,7 @@ func main() {

for _, filename := range sortedFiles {
issues := issuesByFile[filename]
sourceCode, err := lint.ReadSourceCode(filename)
sourceCode, err := internal.ReadSourceCode(filename)
if err != nil {
fmt.Printf("error reading source file %s: %v\n", filename, err)
continue
Expand All @@ -96,7 +97,7 @@ func main() {
}
}

func processFile(engine *lint.Engine, filePath string) ([]lint.Issue, error) {
func processFile(engine *internal.Engine, filePath string) ([]lints.Issue, error) {
issues, err := engine.Run(filePath)
if err != nil {
return nil, fmt.Errorf("error linting %s: %w", filePath, err)
Expand Down
11 changes: 6 additions & 5 deletions formatter/fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/fatih/color"
"github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal/lints"
)

// rule set
Expand All @@ -18,12 +19,12 @@ const (
// IssueFormatter is the interface that wraps the Format method.
// Implementations of this interface are responsible for formatting specific types of lint issues.
type IssueFormatter interface {
Format(issue internal.Issue, snippet *internal.SourceCode) string
Format(issue lints.Issue, snippet *internal.SourceCode) string
}

// FormatIssuesWithArrows formats a slice of issues into a human-readable string.
// It uses the appropriate formatter for each issue based on its rule.
func FormatIssuesWithArrows(issues []internal.Issue, snippet *internal.SourceCode) string {
func FormatIssuesWithArrows(issues []lints.Issue, snippet *internal.SourceCode) string {
var builder strings.Builder
for _, issue := range issues {
builder.WriteString(formatIssueHeader(issue))
Expand Down Expand Up @@ -51,19 +52,19 @@ func getFormatter(rule string) IssueFormatter {

// formatIssueHeader creates a formatted header string for a given issue.
// The header includes the rule and the filename. (e.g. "error: unused-variable\n --> test.go")
func formatIssueHeader(issue internal.Issue) string {
func formatIssueHeader(issue lints.Issue) string {
return errorStyle.Sprint("error: ") + ruleStyle.Sprint(issue.Rule) + "\n" +
lineStyle.Sprint(" --> ") + fileStyle.Sprint(issue.Filename) + "\n"
}

func buildSuggestion(result *strings.Builder, issue internal.Issue, lineStyle, suggestionStyle *color.Color) {
func buildSuggestion(result *strings.Builder, issue lints.Issue, lineStyle, suggestionStyle *color.Color) {
result.WriteString(suggestionStyle.Sprintf("Suggestion:\n"))
result.WriteString(lineStyle.Sprintf("%d | ", issue.Start.Line))
result.WriteString(fmt.Sprintf("%s\n", issue.Suggestion))
result.WriteString("\n")
}

func buildNote(result *strings.Builder, issue internal.Issue, suggestionStyle *color.Color) {
func buildNote(result *strings.Builder, issue lints.Issue, suggestionStyle *color.Color) {
result.WriteString(suggestionStyle.Sprint("Note: "))
result.WriteString(fmt.Sprintf("%s\n", issue.Note))
result.WriteString("\n")
Expand Down
9 changes: 5 additions & 4 deletions formatter/fmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal/lints"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand All @@ -24,7 +25,7 @@ func TestFormatIssuesWithArrows(t *testing.T) {
},
}

issues := []internal.Issue{
issues := []lints.Issue{
{
Rule: "unused-variable",
Filename: "test.go",
Expand Down Expand Up @@ -106,7 +107,7 @@ func TestFormatIssuesWithArrows_MultipleDigitsLineNumbers(t *testing.T) {
},
}

issues := []internal.Issue{
issues := []lints.Issue{
{
Rule: "unused-variable",
Filename: "test.go",
Expand Down Expand Up @@ -170,7 +171,7 @@ func TestFormatIssuesWithArrows_UnnecessaryElse(t *testing.T) {
},
}

issues := []internal.Issue{
issues := []lints.Issue{
{
Rule: "unnecessary-else",
Filename: "test.go",
Expand Down Expand Up @@ -300,7 +301,7 @@ func main() {
func TestUnnecessaryTypeConversionFormatter(t *testing.T) {
formatter := &UnnecessaryTypeConversionFormatter{}

issue := internal.Issue{
issue := lints.Issue{
Rule: "unnecessary-type-conversion",
Filename: "test.go",
Start: token.Position{Line: 5, Column: 10},
Expand Down
3 changes: 2 additions & 1 deletion formatter/general.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/fatih/color"
"github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal/lints"
)

const tabWidth = 8
Expand All @@ -25,7 +26,7 @@ type GeneralIssueFormatter struct{}
// Format formats a general lint issue into a human-readable string.
// It takes an Issue and a SourceCode snippet as input and returns a formatted string.
func (f *GeneralIssueFormatter) Format(
issue internal.Issue,
issue lints.Issue,
snippet *internal.SourceCode,
) string {
var result strings.Builder
Expand Down
3 changes: 2 additions & 1 deletion formatter/simplify_slice_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import (
"strings"

"github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal/lints"
)

type SimplifySliceExpressionFormatter struct{}

func (f *SimplifySliceExpressionFormatter) Format(
issue internal.Issue,
issue lints.Issue,
snippet *internal.SourceCode,
) string {
var result strings.Builder
Expand Down
5 changes: 3 additions & 2 deletions formatter/unnecessary_else.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"strings"

"github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal/lints"
)

// UnnecessaryElseFormatter is a formatter specifically designed for the "unnecessary-else" rule.
type UnnecessaryElseFormatter struct{}

func (f *UnnecessaryElseFormatter) Format(
issue internal.Issue,
issue lints.Issue,
snippet *internal.SourceCode,
) string {
var result strings.Builder
Expand Down Expand Up @@ -61,7 +62,7 @@ func calculateMaxLineLength(lines []string, start, end int) int {
return maxLen
}

func formatSuggestion(issue internal.Issue, improvedSnippet string, startLine int) string {
func formatSuggestion(issue lints.Issue, improvedSnippet string, startLine int) string {
var result strings.Builder
lines := strings.Split(improvedSnippet, "\n")
maxLineNumWidth := calculateMaxLineNumWidth(issue.End.Line)
Expand Down
3 changes: 2 additions & 1 deletion formatter/unnecessary_type_conv.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import (
"strings"

"github.com/gnoswap-labs/lint/internal"
"github.com/gnoswap-labs/lint/internal/lints"
)

type UnnecessaryTypeConversionFormatter struct{}

func (f *UnnecessaryTypeConversionFormatter) Format(
issue internal.Issue,
issue lints.Issue,
snippet *internal.SourceCode,
) string {
var result strings.Builder
Expand Down
15 changes: 11 additions & 4 deletions internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"os"
"path/filepath"
"strings"

"github.com/gnoswap-labs/lint/internal/lints"
)

// Engine manages the linting process.
Expand Down Expand Up @@ -43,14 +45,14 @@ func (e *Engine) AddRule(rule LintRule) {
}

// Run applies all lint rules to the given file and returns a slice of Issues.
func (e *Engine) Run(filename string) ([]Issue, error) {
func (e *Engine) Run(filename string) ([]lints.Issue, error) {
tempFile, err := e.prepareFile(filename)
if err != nil {
return nil, err
}
defer e.cleanupTemp(tempFile)

var allIssues []Issue
var allIssues []lints.Issue
for _, rule := range e.rules {
issues, err := rule.Check(tempFile)
if err != nil {
Expand Down Expand Up @@ -84,8 +86,8 @@ func (e *Engine) cleanupTemp(temp string) {
}
}

func (e *Engine) filterUndefinedIssues(issues []Issue) []Issue {
var filtered []Issue
func (e *Engine) filterUndefinedIssues(issues []lints.Issue) []lints.Issue {
var filtered []lints.Issue
for _, issue := range issues {
if issue.Rule == "typecheck" && strings.Contains(issue.Message, "undefined:") {
symbol := strings.TrimSpace(strings.TrimPrefix(issue.Message, "undefined:"))
Expand Down Expand Up @@ -126,6 +128,11 @@ func createTempGoFile(gnoFile string) (string, error) {
return tempFile.Name(), nil
}

// SourceCode stores the content of a source code file.
type SourceCode struct {
Lines []string
}

// ReadSourceFile reads the content of a file and returns it as a `SourceCode` struct.
func ReadSourceCode(filename string) (*SourceCode, error) {
content, err := os.ReadFile(filename)
Expand Down
4 changes: 3 additions & 1 deletion internal/fixer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"go/parser"
"go/token"
"strings"

"github.com/gnoswap-labs/lint/internal/lints"
)

func RemoveUnnecessaryElse(snippet string) (string, error) {
Expand Down Expand Up @@ -121,7 +123,7 @@ func insertStatementsAfter(block *ast.BlockStmt, target ast.Stmt, stmts []ast.St
}
}

func ExtractSnippet(issue Issue, code string, startLine, endLine int) string {
func ExtractSnippet(issue lints.Issue, code string, startLine, endLine int) string {
lines := strings.Split(code, "\n")

// ensure we don't go out of bounds
Expand Down
Loading

0 comments on commit df1127d

Please sign in to comment.