Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize Structure #13

Merged
merged 2 commits into from
Jul 19, 2024
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
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
Loading