From 0c956c5aef5b5fcb87004864600a540f5c4e689d Mon Sep 17 00:00:00 2001 From: Bastian Doetsch Date: Fri, 18 Oct 2024 10:15:40 +0200 Subject: [PATCH] fix: golangci config, linter errors (#704) --- .golangci.yaml | 38 +++---- application/codeaction/codeaction.go | 2 +- application/config/config.go | 1 + application/di/init.go | 1 + application/entrypoint/helpers.go | 15 ++- application/server/configuration.go | 1 + application/server/configuration_test.go | 3 +- application/server/execute_command_test.go | 23 ++-- .../server/notification/scan_notifier_test.go | 6 +- application/server/server_test.go | 9 -- ast/maven/parser.go | 3 +- domain/ide/codelens/codelens.go | 11 +- domain/ide/command/clear_cache.go | 17 ++- domain/ide/command/clear_cache_test.go | 6 +- domain/ide/command/code_fix.go | 52 +++++++-- domain/ide/command/code_fix_feedback.go | 12 +- domain/ide/command/code_fix_test.go | 14 ++- domain/ide/command/command_factory.go | 1 + domain/ide/command/execute_cli.go | 11 +- .../ide/command/generate_issue_description.go | 2 + domain/ide/command/get_active_user_test.go | 1 + domain/ide/command/get_learn_lesson.go | 28 ++++- domain/ide/command/navigate_to_range.go | 8 +- domain/ide/command/open_browser.go | 8 +- domain/ide/command/report_analytics_test.go | 1 + domain/ide/command/workspace_folder_scan.go | 6 +- domain/ide/workspace/folder.go | 17 ++- domain/ide/workspace/folder_test.go | 1 + domain/ide/workspace/workspace.go | 3 +- domain/ide/workspace/workspace_test.go | 3 +- domain/snyk/code_issue_data.go | 4 +- domain/snyk/persistence/file_operation.go | 4 +- .../persistence/git_persistence_provider.go | 1 + .../git_persistence_provider_test.go | 12 +- domain/snyk/scanner/scanner_test.go | 5 +- domain/snyk/scanner/test_product_scanner.go | 3 +- domain/snyk/scanner/test_scanner.go | 3 +- .../authentication/auth_configuration.go | 1 + .../authentication/auth_configuration_test.go | 1 + .../authentication_functions.go | 1 + infrastructure/cli/cli.go | 1 + infrastructure/cli/cli_extension_executor.go | 13 ++- infrastructure/cli/environment.go | 1 + infrastructure/cli/install/discovery.go | 2 +- infrastructure/cli/install/releases.go | 1 + infrastructure/cli/install/releases_test.go | 1 + infrastructure/code/autofix.go | 1 + infrastructure/code/code.go | 1 + infrastructure/code/code_error_reporter.go | 3 +- infrastructure/code/code_html.go | 8 +- infrastructure/code/code_instrumentor.go | 1 + infrastructure/code/code_tracker.go | 1 + infrastructure/code/convert_test.go | 2 +- .../code/fake_snyk_code_api_service.go | 2 +- infrastructure/code/issue_enhancer.go | 10 +- infrastructure/code/snyk_code_http_client.go | 1 + .../code/snyk_code_http_client_interface.go | 1 + infrastructure/iac/iac.go | 35 +++--- infrastructure/iac/iac_html.go | 10 +- infrastructure/learn/service.go | 1 + infrastructure/oss/cli_scanner.go | 2 +- infrastructure/oss/code_actions.go | 24 +++- infrastructure/oss/oss_html.go | 5 +- infrastructure/oss/types.go | 6 +- infrastructure/snyk_api/snyk_api.go | 4 +- infrastructure/utils/fingerprint.go | 3 +- internal/concurrency/atomic_map.go | 80 -------------- internal/concurrency/atomic_map_test.go | 103 ------------------ internal/delta/delta_finder_test.go | 3 +- internal/delta/fuzzy_matcher.go | 5 +- internal/delta/fuzzy_matcher_test.go | 3 +- internal/html/nonce.go | 2 +- internal/logging/lsp_logger.go | 8 +- internal/notification/notifier_mock.go | 8 +- .../observability/performance/noop_span.go | 4 +- internal/sdk/sdk.go | 1 + internal/types/command.go | 3 +- internal/types/grouping.go | 14 ++- internal/vcs/git_cloner.go | 5 +- internal/vcs/git_cloner_test.go | 10 +- internal/vcs/git_utils.go | 6 +- ls_extension/main.go | 4 +- main.go | 2 +- main_test.go | 3 - 84 files changed, 373 insertions(+), 370 deletions(-) delete mode 100644 internal/concurrency/atomic_map.go delete mode 100644 internal/concurrency/atomic_map_test.go diff --git a/.golangci.yaml b/.golangci.yaml index 7dae4cd3b..aa96c8875 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -3,15 +3,6 @@ run: - integration concurrency: 4 issues-exit-code: 1 - skip-dirs: - - "docs" - - "licenses" - - "pact" - - "ampli" - - ".bin" - - ".github" - - ".vscode" - - "build" tests: true timeout: 5m @@ -40,7 +31,6 @@ linters-settings: gosimple: checks: ['all'] govet: - check-shadowing: true enable-all: true disable: - fieldalignment @@ -69,7 +59,6 @@ linters-settings: - name: error-strings - name: error-naming - name: exported - disable-stuttering-check: true - name: if-return - name: increment-decrement - name: var-naming @@ -92,8 +81,6 @@ linters-settings: stylecheck: checks: ['all'] http-status-code-whitelist: [] - varcheck: - exported-fields: true linters: enable: @@ -109,14 +96,11 @@ linters: - dupl - durationcheck - errname - # TODO(errorlint): revisit - #- errorlint + - errorlint - exhaustive - - exportloopref - # TODO(forbidigo): revisit - #- forbidigo - # TODO(forcetypeassert): revisit this one! beware fragile asserts in this codebase - #- forcetypeassert + - copyloopvar + - forbidigo + - forcetypeassert # TODO(goconst): revisit #- goconst # TODO(gocritic): revisit @@ -127,7 +111,7 @@ linters: # TODO(gofumpt): revisit #- gofumpt # TODO(goimports): revisit - #- goimports + - goimports - goprintffuncname # TODO(gosec): revisit; consequences of revoking non-owner file permissions? #- gosec @@ -153,7 +137,7 @@ linters: - predeclared - promlinter # TODO(revive): revisit in a followup; extensive changes, some breaking. godoc requirement would be good to introduce - #- revive + # - revive - rowserrcheck - sqlclosecheck # TODO(stylecheck): revisit in a followup; some breaking API changes @@ -174,6 +158,16 @@ linters: #- wrapcheck issues: + exclude-dirs: + - "docs" + - "licenses" + - "pact" + - "ampli" + - ".bin" + - ".github" + - ".vscode" + - "build" + exclude-rules: - path: _test\.go linters: diff --git a/application/codeaction/codeaction.go b/application/codeaction/codeaction.go index 4d1eb9f67..85fea8f8f 100644 --- a/application/codeaction/codeaction.go +++ b/application/codeaction/codeaction.go @@ -120,7 +120,7 @@ func (c *CodeActionsService) getQuickFixAction(quickFixGroupables []types.Groupa // right now we can always group by max semver version, as // code only has one quickfix available, and iac none at all var quickFix *snyk.CodeAction - qf, ok := types.MaxSemver()(quickFixGroupables).(snyk.CodeAction) + qf, ok := types.MaxSemver(c.logger)(quickFixGroupables).(snyk.CodeAction) if !ok { c.logger.Warn().Msg("grouping quick fix actions failed") quickFix = nil diff --git a/application/config/config.go b/application/config/config.go index 48a98772e..84e05a719 100644 --- a/application/config/config.go +++ b/application/config/config.go @@ -45,6 +45,7 @@ import ( frameworkLogging "github.com/snyk/go-application-framework/pkg/logging" "github.com/snyk/go-application-framework/pkg/runtimeinfo" "github.com/snyk/go-application-framework/pkg/workflow" + "github.com/snyk/snyk-ls/infrastructure/cli/cli_constants" "github.com/snyk/snyk-ls/infrastructure/cli/filename" "github.com/snyk/snyk-ls/internal/concurrency" diff --git a/application/di/init.go b/application/di/init.go index a00e9a59b..31fb53041 100644 --- a/application/di/init.go +++ b/application/di/init.go @@ -30,6 +30,7 @@ import ( codeClient "github.com/snyk/code-client-go" codeClientHTTP "github.com/snyk/code-client-go/http" codeClientObservability "github.com/snyk/code-client-go/observability" + "github.com/snyk/snyk-ls/application/codeaction" "github.com/snyk/snyk-ls/application/config" appNotification "github.com/snyk/snyk-ls/application/server/notification" diff --git a/application/entrypoint/helpers.go b/application/entrypoint/helpers.go index 148db0f81..a7600afe9 100644 --- a/application/entrypoint/helpers.go +++ b/application/entrypoint/helpers.go @@ -13,8 +13,8 @@ import ( func OnPanicRecover() { if err := recover(); err != nil { panickingMsg := "🚨 Panicking 🚨" - fmt.Println(panickingMsg) - fmt.Println(err) + _, _ = fmt.Fprintln(os.Stderr, panickingMsg) + _, _ = fmt.Fprintln(os.Stderr, err) debug.PrintStack() c := config.CurrentConfig() @@ -31,10 +31,9 @@ func OnPanicRecover() { } func PrintLicenseText(output string) { - fmt.Fprintln(os.Stderr, "License information") - fmt.Fprintln(os.Stderr, "Snyk Language Server is licensed under the Apache 2.0 license") - fmt.Fprintln(os.Stderr, "The following dependencies and licenses are used in this project:") - fmt.Fprintln(os.Stderr, strings.ReplaceAll(output, " ", "\n")) - fmt.Fprintln(os.Stderr, - "You can access the detailed license information under https://github.com/snyk/snyk-ls/tree/main/licenses") + _, _ = fmt.Fprintln(os.Stderr, "License information") + _, _ = fmt.Fprintln(os.Stderr, "Snyk Language Server is licensed under the Apache 2.0 license") + _, _ = fmt.Fprintln(os.Stderr, "The following dependencies and licenses are used in this project:") + _, _ = fmt.Fprintln(os.Stderr, strings.ReplaceAll(output, " ", "\n")) + _, _ = fmt.Fprintln(os.Stderr, "You can access the detailed license information under https://github.com/snyk/snyk-ls/tree/main/licenses") } diff --git a/application/server/configuration.go b/application/server/configuration.go index fdbd5b6b3..c614d6fd6 100644 --- a/application/server/configuration.go +++ b/application/server/configuration.go @@ -29,6 +29,7 @@ import ( "github.com/creachadair/jrpc2/handler" "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/application/di" "github.com/snyk/snyk-ls/domain/ide/workspace" diff --git a/application/server/configuration_test.go b/application/server/configuration_test.go index 609e45025..3e344f1d3 100644 --- a/application/server/configuration_test.go +++ b/application/server/configuration_test.go @@ -18,7 +18,6 @@ package server import ( "context" - "fmt" "os" "path/filepath" "strconv" @@ -33,6 +32,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/application/config" @@ -59,7 +59,6 @@ var sampleSettings = types.Settings{ func keyFoundInEnv(key string) bool { found := false env := os.Environ() - fmt.Println(env) for _, v := range env { if strings.HasPrefix(v, key+"=") { found = true diff --git a/application/server/execute_command_test.go b/application/server/execute_command_test.go index 3ece40c9a..e41dc04d0 100644 --- a/application/server/execute_command_test.go +++ b/application/server/execute_command_test.go @@ -18,11 +18,12 @@ package server import ( "context" - "github.com/snyk/snyk-ls/domain/snyk" - "github.com/snyk/snyk-ls/domain/snyk/scanner" "testing" "time" + "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/domain/snyk/scanner" + "github.com/sourcegraph/go-lsp" "github.com/stretchr/testify/assert" @@ -38,8 +39,8 @@ func Test_executeWorkspaceScanCommand_shouldStartWorkspaceScanOnCommandReceipt(t loc, _ := setupServerWithCustomDI(t, false) c := config.CurrentConfig() - scanner := &scanner.TestScanner{} - workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", scanner, di.HoverService(), di.ScanNotifier(), di.Notifier(), di.ScanPersister())) + s := &scanner.TestScanner{} + workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", s, di.HoverService(), di.ScanNotifier(), di.Notifier(), di.ScanPersister())) params := lsp.ExecuteCommandParams{Command: types.WorkspaceScanCommand} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) @@ -47,7 +48,7 @@ func Test_executeWorkspaceScanCommand_shouldStartWorkspaceScanOnCommandReceipt(t t.Fatal(err) } assert.Eventually(t, func() bool { - return scanner.Calls() > 0 + return s.Calls() > 0 }, 2*time.Second, time.Millisecond) } @@ -55,8 +56,8 @@ func Test_executeWorkspaceFolderScanCommand_shouldStartFolderScanOnCommandReceip loc, _ := setupServerWithCustomDI(t, false) c := config.CurrentConfig() - scanner := &scanner.TestScanner{} - workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", scanner, di.HoverService(), di.ScanNotifier(), di.Notifier(), di.ScanPersister())) + s := &scanner.TestScanner{} + workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", s, di.HoverService(), di.ScanNotifier(), di.Notifier(), di.ScanPersister())) params := lsp.ExecuteCommandParams{Command: types.WorkspaceFolderScanCommand, Arguments: []any{"dummy"}} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) @@ -64,7 +65,7 @@ func Test_executeWorkspaceFolderScanCommand_shouldStartFolderScanOnCommandReceip t.Fatal(err) } assert.Eventually(t, func() bool { - return scanner.Calls() > 0 + return s.Calls() > 0 }, 2*time.Second, time.Millisecond) } @@ -105,8 +106,8 @@ func Test_executeWorkspaceScanCommand_shouldAskForTrust(t *testing.T) { loc, jsonRPCRecorder := setupServerWithCustomDI(t, false) c := config.CurrentConfig() - scanner := &scanner.TestScanner{} - workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", scanner, di.HoverService(), di.ScanNotifier(), di.Notifier(), di.ScanPersister())) + s := &scanner.TestScanner{} + workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", s, di.HoverService(), di.ScanNotifier(), di.Notifier(), di.ScanPersister())) // explicitly enable folder trust which is disabled by default in tests config.CurrentConfig().SetTrustedFolderFeatureEnabled(true) @@ -116,7 +117,7 @@ func Test_executeWorkspaceScanCommand_shouldAskForTrust(t *testing.T) { t.Fatal(err) } assert.Eventually(t, func() bool { - return scanner.Calls() == 0 && checkTrustMessageRequest(jsonRPCRecorder) + return s.Calls() == 0 && checkTrustMessageRequest(jsonRPCRecorder) }, 2*time.Second, time.Millisecond) } diff --git a/application/server/notification/scan_notifier_test.go b/application/server/notification/scan_notifier_test.go index 816a5ba5c..7fa98ed4c 100644 --- a/application/server/notification/scan_notifier_test.go +++ b/application/server/notification/scan_notifier_test.go @@ -17,14 +17,16 @@ package notification_test import ( + "testing" + + "github.com/stretchr/testify/assert" + notification2 "github.com/snyk/snyk-ls/application/server/notification" "github.com/snyk/snyk-ls/domain/snyk/scanner" "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/types" - "github.com/stretchr/testify/assert" - "testing" ) type sendMessageTestCase struct { diff --git a/application/server/server_test.go b/application/server/server_test.go index 809bab48e..9f2dbd967 100644 --- a/application/server/server_test.go +++ b/application/server/server_test.go @@ -18,7 +18,6 @@ package server import ( "context" - "fmt" "os" "os/exec" "path/filepath" @@ -156,14 +155,6 @@ func startServer(callBackFn onCallbackFn, jsonRPCRecorder *testutil.JsonRPCRecor return loc } -func Test_serverShouldStart(t *testing.T) { - loc, _ := setupServer(t) - - si := loc.Server.ServerInfo() - - fmt.Println(strings.Join(si.Methods, "\n")) -} - func Test_dummy_shouldNotBeServed(t *testing.T) { loc, _ := setupServer(t) diff --git a/ast/maven/parser.go b/ast/maven/parser.go index 6ab47ffb6..dac11ddf5 100644 --- a/ast/maven/parser.go +++ b/ast/maven/parser.go @@ -18,6 +18,7 @@ package maven import ( "encoding/xml" + "errors" "io" "strings" @@ -50,7 +51,7 @@ func (p *Parser) Parse(content string, path string) ast.Tree { for { token, err := d.Token() offset = d.InputOffset() - if token == nil || err == io.EOF { + if token == nil || errors.Is(err, io.EOF) { // EOF means we're done. break } else if err != nil { diff --git a/domain/ide/codelens/codelens.go b/domain/ide/codelens/codelens.go index 626db4501..f517b9298 100644 --- a/domain/ide/codelens/codelens.go +++ b/domain/ide/codelens/codelens.go @@ -19,6 +19,7 @@ package codelens import ( "fmt" + "github.com/rs/zerolog" sglsp "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" @@ -35,6 +36,8 @@ type lensesWithIssueCount struct { } func GetFor(filePath string) (lenses []sglsp.CodeLens) { + c := config.CurrentConfig() + logger := c.Logger().With().Str("method", "codelens.GetFor").Str("filePath", filePath).Logger() f := workspace.Get().GetFolderContaining(filePath) if f == nil { return lenses @@ -45,7 +48,7 @@ func GetFor(filePath string) (lenses []sglsp.CodeLens) { // group by range first lensesByRange := make(map[snyk.Range]*lensesWithIssueCount) for _, issue := range issues { - if config.CurrentConfig().IsDeltaFindingsEnabled() && !issue.IsNew { + if c.IsDeltaFindingsEnabled() && !issue.IsNew { continue } for _, lens := range issue.CodelensCommands { @@ -64,7 +67,7 @@ func GetFor(filePath string) (lenses []sglsp.CodeLens) { } for r, commands := range lensesByRange { - lensCommands := getLensCommands(commands) + lensCommands := getLensCommands(commands, logger) for _, command := range lensCommands { lens := getCodeLensFromCommand(r, command) lenses = append(lenses, lens) @@ -74,7 +77,7 @@ func GetFor(filePath string) (lenses []sglsp.CodeLens) { return lenses } -func getLensCommands(lensesWithIssueCount *lensesWithIssueCount) []types.CommandData { +func getLensCommands(lensesWithIssueCount *lensesWithIssueCount, logger zerolog.Logger) []types.CommandData { groupableByType := map[types.GroupingType][]types.Groupable{} for _, groupable := range lensesWithIssueCount.lensCommands { commands := groupableByType[groupable.GetGroupingType()] @@ -90,7 +93,7 @@ func getLensCommands(lensesWithIssueCount *lensesWithIssueCount) []types.Command if groupingType == types.Quickfix { // right now we can always group by max semver version, as // code only has one quickfix available, and iac none at all - qf, ok := types.MaxSemver()(lensCommands).(types.CommandData) + qf, ok := types.MaxSemver(logger)(lensCommands).(types.CommandData) plural := "" fixable := lensesWithIssueCount.issueCount unfixable := lensesWithIssueCount.totalIssues - fixable diff --git a/domain/ide/command/clear_cache.go b/domain/ide/command/clear_cache.go index 710d3f48f..8fbb4d4e4 100644 --- a/domain/ide/command/clear_cache.go +++ b/domain/ide/command/clear_cache.go @@ -18,12 +18,15 @@ package command import ( "context" + "fmt" + "net/url" + "github.com/rs/zerolog" + "github.com/sourcegraph/go-lsp" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/workspace" "github.com/snyk/snyk-ls/internal/types" - "github.com/sourcegraph/go-lsp" - "net/url" ) type clearCache struct { @@ -41,7 +44,10 @@ func (cmd *clearCache) Execute(_ context.Context) (any, error) { logger := config.CurrentConfig().Logger().With().Str("method", "clearCache.Execute").Logger() args := cmd.command.Arguments var parsedFolderUri *lsp.DocumentURI - folderURI := args[0].(string) + folderURI, ok := args[0].(string) + if !ok { + return nil, fmt.Errorf("invalid folder URI") + } if folderURI != "" { decodedPath, err := url.PathUnescape(folderURI) @@ -53,7 +59,10 @@ func (cmd *clearCache) Execute(_ context.Context) (any, error) { parsedFolderUri = &uri } - cacheType := args[1].(string) + cacheType, ok := args[1].(string) + if !ok { + return nil, fmt.Errorf("invalid cache URI") + } if cacheType == "" { cmd.purgeInMemoryCache(&logger, parsedFolderUri) diff --git a/domain/ide/command/clear_cache_test.go b/domain/ide/command/clear_cache_test.go index 5328205ec..61932ee94 100644 --- a/domain/ide/command/clear_cache_test.go +++ b/domain/ide/command/clear_cache_test.go @@ -18,6 +18,10 @@ package command import ( "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/snyk/snyk-ls/domain/ide/workspace" "github.com/snyk/snyk-ls/domain/snyk/persistence" "github.com/snyk/snyk-ls/domain/snyk/scanner" @@ -25,8 +29,6 @@ import ( "github.com/snyk/snyk-ls/internal/observability/performance" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/types" - "github.com/stretchr/testify/assert" - "testing" ) func Test_ClearCache_DeleteAll_NoError(t *testing.T) { diff --git a/domain/ide/command/code_fix.go b/domain/ide/command/code_fix.go index 7024acff8..9d87e9785 100644 --- a/domain/ide/command/code_fix.go +++ b/domain/ide/command/code_fix.go @@ -19,6 +19,7 @@ package command import ( "context" "errors" + "fmt" "time" "github.com/google/uuid" @@ -51,10 +52,16 @@ func (cmd *fixCodeIssue) Execute(_ context.Context) (any, error) { args := cmd.command.Arguments codeActionId, err := uuid.Parse(args[0].(string)) if err != nil { - return nil, errors.New("Failed to parse code action id.") + return nil, errors.Join(err, fmt.Errorf("Failed to parse code action id.")) + } + issuePath, ok := args[1].(string) + if !ok { + return nil, fmt.Errorf("Failed to parse issue path.") + } + issueRange, err := cmd.toRange(args[2]) + if err != nil { + return nil, errors.Join(err, fmt.Errorf("invalid range parameter")) } - issuePath := args[1].(string) - issueRange := cmd.toRange(args[2]) issues := cmd.issueProvider.IssuesForRange(issuePath, issueRange) for i := range issues { @@ -91,14 +98,39 @@ func (cmd *fixCodeIssue) Execute(_ context.Context) (any, error) { type RangeDto = map[string]interface{} type RangePositionDto = map[string]interface{} -func (cmd *fixCodeIssue) toRange(rangeArg any) snyk.Range { - dto := rangeArg.(RangeDto) +func (cmd *fixCodeIssue) toRange(rangeArg any) (snyk.Range, error) { + dto, ok := rangeArg.(RangeDto) + if !ok { + return snyk.Range{}, fmt.Errorf("invalid range parameter") + } startPos := dto["Start"] endPos := dto["End"] - startLine := startPos.(RangePositionDto)["Line"].(float64) - startChar := startPos.(RangePositionDto)["Character"].(float64) - endLine := endPos.(RangePositionDto)["Line"].(float64) - endChar := endPos.(RangePositionDto)["Character"].(float64) + startPosDto, ok := startPos.(RangePositionDto) + if !ok { + return snyk.Range{}, fmt.Errorf("invalid start position parameter") + } + startPosLine, ok := startPosDto["Line"].(float64) + if !ok { + return snyk.Range{}, fmt.Errorf("invalid start position line") + } + startLine := startPosLine + startChar, ok := startPosDto["Character"].(float64) + if !ok { + return snyk.Range{}, fmt.Errorf("invalid start position character") + } + endPosDto, ok := endPos.(RangePositionDto) + if !ok { + return snyk.Range{}, fmt.Errorf("invalid end position parameter") + } + + endLine, ok := endPosDto["Line"].(float64) + if !ok { + return snyk.Range{}, fmt.Errorf("invalid end position line") + } + endChar, ok := endPosDto["Character"].(float64) + if !ok { + return snyk.Range{}, fmt.Errorf("invalid end position character") + } snykRange := snyk.Range{ Start: snyk.Position{ @@ -110,5 +142,5 @@ func (cmd *fixCodeIssue) toRange(rangeArg any) snyk.Range { Character: int(endChar), }, } - return snykRange + return snykRange, nil } diff --git a/domain/ide/command/code_fix_feedback.go b/domain/ide/command/code_fix_feedback.go index 296371465..74b61dd87 100644 --- a/domain/ide/command/code_fix_feedback.go +++ b/domain/ide/command/code_fix_feedback.go @@ -18,6 +18,8 @@ package command import ( "context" + "fmt" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/types" ) @@ -37,8 +39,14 @@ func (cmd *codeFixFeedback) Command() types.CommandData { func (cmd *codeFixFeedback) Execute(ctx context.Context) (any, error) { args := cmd.command.Arguments - fixId := args[0].(string) - feedback := args[1].(string) + fixId, ok := args[0].(string) + if !ok { + return nil, fmt.Errorf("fix id should be a string") + } + feedback, ok := args[1].(string) + if !ok { + return nil, fmt.Errorf("feedback should be a string") + } go func() { err := cmd.apiClient.SubmitAutofixFeedback(ctx, fixId, feedback) diff --git a/domain/ide/command/code_fix_test.go b/domain/ide/command/code_fix_test.go index 69a0a334d..09051fbca 100644 --- a/domain/ide/command/code_fix_test.go +++ b/domain/ide/command/code_fix_test.go @@ -23,6 +23,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/converter" @@ -144,7 +145,8 @@ func Test_fixCodeIssue_sendsSuccessfulEdit(t *testing.T) { cmd := setupCommand(mockNotifier) filePath := sampleArgs[1] - issueRange := cmd.toRange(sampleArgs[2]) + issueRange, err := cmd.toRange(sampleArgs[2]) + require.NoError(t, err) mockEdit, deferredMockEdit := setupMockEdit() codeAction := snyk.CodeAction{ Uuid: &codeActionId, @@ -178,7 +180,10 @@ func Test_fixCodeIssue_noEdit(t *testing.T) { cmd := setupCommand(mockNotifier) filePath := sampleArgs[1] - issueRange := cmd.toRange(sampleArgs[2]) + rangeDto, ok := sampleArgs[2].(RangeDto) + require.True(t, ok) + issueRange, err := cmd.toRange(rangeDto) + require.NoError(t, err) deferredMockEdit := func() *snyk.WorkspaceEdit { return nil } @@ -214,7 +219,10 @@ func Test_fixCodeIssue_NoIssueFound(t *testing.T) { cmd := setupCommand(mockNotifier) filePath := sampleArgs[1] - issueRange := cmd.toRange(sampleArgs[2]) + rangeDto, ok := sampleArgs[2].(RangeDto) + require.True(t, ok) + issueRange, err := cmd.toRange(rangeDto) + require.NoError(t, err) issueProviderMock := new(issueProviderMock) issueProviderMock.On("IssuesForRange", filePath, issueRange).Return([]snyk.Issue{}) diff --git a/domain/ide/command/command_factory.go b/domain/ide/command/command_factory.go index 6db65d673..ad2a65db8 100644 --- a/domain/ide/command/command_factory.go +++ b/domain/ide/command/command_factory.go @@ -18,6 +18,7 @@ package command import ( "fmt" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/authentication" diff --git a/domain/ide/command/execute_cli.go b/domain/ide/command/execute_cli.go index eae1ee5ab..939ab41fd 100644 --- a/domain/ide/command/execute_cli.go +++ b/domain/ide/command/execute_cli.go @@ -52,11 +52,18 @@ func (cmd *executeCLICommand) Execute(ctx context.Context) (any, error) { if len(cmd.command.Arguments) < 2 { return nil, fmt.Errorf("invalid usage of executeCLICommand. First arg needs to be the workDir, then CLI arguments without binary path") } - workDir := cmd.command.Arguments[0].(string) + workDir, ok := cmd.command.Arguments[0].(string) + if !ok { + return nil, fmt.Errorf("workDir needs to be a string") + } args := []string{config.CurrentConfig().CliSettings().Path()} for _, argument := range cmd.command.Arguments[1:] { - args = append(args, argument.(string)) + elems, ok := argument.(string) + if !ok { + return nil, fmt.Errorf("argument needs to be a string") + } + args = append(args, elems) } args = cmd.cli.ExpandParametersFromConfig(args) diff --git a/domain/ide/command/generate_issue_description.go b/domain/ide/command/generate_issue_description.go index a3ccf8623..750b8691f 100644 --- a/domain/ide/command/generate_issue_description.go +++ b/domain/ide/command/generate_issue_description.go @@ -19,7 +19,9 @@ package command import ( "context" "errors" + "github.com/rs/zerolog" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/code" diff --git a/domain/ide/command/get_active_user_test.go b/domain/ide/command/get_active_user_test.go index d2bee480f..6b904553f 100644 --- a/domain/ide/command/get_active_user_test.go +++ b/domain/ide/command/get_active_user_test.go @@ -27,6 +27,7 @@ import ( localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/workflow" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/observability/error_reporting" diff --git a/domain/ide/command/get_learn_lesson.go b/domain/ide/command/get_learn_lesson.go index 9eb26e501..bfd5565ea 100644 --- a/domain/ide/command/get_learn_lesson.go +++ b/domain/ide/command/get_learn_lesson.go @@ -48,12 +48,30 @@ func (cmd *getLearnLesson) Execute(_ context.Context) (any, error) { } func learnLesson(args []any, learnService learn.Service) (*learn.Lesson, error) { - rule := args[0].(string) - ecosystem := args[1].(string) - cwes := strings.Split(args[2].(string), ",") - cves := strings.Split(args[3].(string), ",") + rule, ok := args[0].(string) + if !ok { + return nil, errors.New("learn lesson rule is not a string") + } + ecosystem, ok := args[1].(string) + if !ok { + return nil, errors.New("learn lesson ecosystem is not a string") + } + cwesArg, ok := args[2].(string) + if !ok { + return nil, errors.New("learn lesson cwes is not a string") + } + cwes := strings.Split(cwesArg, ",") + cvesArg, ok := args[3].(string) + if !ok { + return nil, errors.New("learn lesson cves is not a string") + } + cves := strings.Split(cvesArg, ",") // json numbers are mapped to float64 (https://pkg.go.dev/encoding/json#Unmarshal) - issueType := snyk.Type(args[4].(float64)) + issueTypeArg, ok := args[4].(float64) + if !ok { + return nil, errors.New("learn lesson issueType is not a number") + } + issueType := snyk.Type(issueTypeArg) lesson, err := learnService.GetLesson(ecosystem, rule, cwes, cves, issueType) if err != nil { diff --git a/domain/ide/command/navigate_to_range.go b/domain/ide/command/navigate_to_range.go index 48f36890b..0e9726a7d 100644 --- a/domain/ide/command/navigate_to_range.go +++ b/domain/ide/command/navigate_to_range.go @@ -39,7 +39,7 @@ func (cmd *navigateToRangeCommand) Command() types.CommandData { return cmd.command } -func (cmd *navigateToRangeCommand) Execute(ctx context.Context) (any, error) { +func (cmd *navigateToRangeCommand) Execute(_ context.Context) (any, error) { method := "navigateToRangeCommand.Execute" if len(cmd.command.Arguments) < 2 { cmd.logger.Warn().Str("method", method).Msg("received NavigateToRangeCommand without range") @@ -56,8 +56,12 @@ func (cmd *navigateToRangeCommand) Execute(ctx context.Context) (any, error) { return nil, errors.Wrap(err, "couldn't unmarshal range from json") } + path, ok := args[0].(string) + if !ok { + return nil, errors.Errorf("invalid range path: %s", args[0]) + } params := types.ShowDocumentParams{ - Uri: uri.PathToUri(args[0].(string)), + Uri: uri.PathToUri(path), External: false, TakeFocus: true, Selection: converter.ToRange(myRange), diff --git a/domain/ide/command/open_browser.go b/domain/ide/command/open_browser.go index 0f7bf39ee..0b497a6a3 100644 --- a/domain/ide/command/open_browser.go +++ b/domain/ide/command/open_browser.go @@ -18,6 +18,7 @@ package command import ( "context" + "fmt" "github.com/rs/zerolog" @@ -33,8 +34,11 @@ func (cmd *openBrowserCommand) Command() types.CommandData { return cmd.command } -func (cmd *openBrowserCommand) Execute(ctx context.Context) (any, error) { - url := cmd.command.Arguments[0].(string) +func (cmd *openBrowserCommand) Execute(_ context.Context) (any, error) { + url, ok := cmd.command.Arguments[0].(string) + if !ok { + return nil, fmt.Errorf("invalid url") + } cmd.logger.Debug().Str("method", "openBrowserCommand.Execute").Msgf("opening browser url %s", url) types.DefaultOpenBrowserFunc(url) return nil, nil diff --git a/domain/ide/command/report_analytics_test.go b/domain/ide/command/report_analytics_test.go index e8ea95454..4356ce810 100644 --- a/domain/ide/command/report_analytics_test.go +++ b/domain/ide/command/report_analytics_test.go @@ -23,6 +23,7 @@ import ( "github.com/golang/mock/gomock" localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/internal/notification" diff --git a/domain/ide/command/workspace_folder_scan.go b/domain/ide/command/workspace_folder_scan.go index 0a80a709d..40dc97075 100644 --- a/domain/ide/command/workspace_folder_scan.go +++ b/domain/ide/command/workspace_folder_scan.go @@ -18,6 +18,7 @@ package command import ( "context" + "fmt" "github.com/pkg/errors" "github.com/rs/zerolog" @@ -45,7 +46,10 @@ func (cmd *workspaceFolderScanCommand) Execute(ctx context.Context) (any, error) cmd.logger.Warn().Str("method", method).Err(err).Send() return nil, err } - path := args[0].(string) + path, ok := args[0].(string) + if !ok { + return nil, fmt.Errorf("received WorkspaceFolderScanCommand with invalid path") + } f := w.GetFolderContaining(path) if f == nil { err := errors.New("received WorkspaceFolderScanCommand with path not in workspace") diff --git a/domain/ide/workspace/folder.go b/domain/ide/workspace/folder.go index 99e02be19..e7e31c307 100644 --- a/domain/ide/workspace/folder.go +++ b/domain/ide/workspace/folder.go @@ -20,10 +20,11 @@ import ( "context" "encoding/json" "fmt" - "github.com/sourcegraph/go-lsp" "strings" "sync" + "github.com/sourcegraph/go-lsp" + "github.com/snyk/snyk-ls/domain/ide/workspace/ui" "github.com/snyk/snyk-ls/domain/snyk" delta2 "github.com/snyk/snyk-ls/domain/snyk/delta" @@ -93,8 +94,8 @@ func (f *Folder) Issue(key string) snyk.Issue { }) if foundIssue.ID == "" { - if scanner, ok := f.scanner.(snyk.IssueProvider); ok { - foundIssue = scanner.Issue(key) + if issueProvider, ok := f.scanner.(snyk.IssueProvider); ok { + foundIssue = issueProvider.Issue(key) } } return foundIssue @@ -148,8 +149,8 @@ func (f *Folder) IssuesByProduct() snyk.ProductIssuesByFile { func (f *Folder) IssuesForFile(file string) []snyk.Issue { // try to delegate to scanners first var issues []snyk.Issue - if scanner, ok := f.scanner.(snyk.IssueProvider); ok { - issues = append(issues, scanner.IssuesForFile(file)...) + if issueProvider, ok := f.scanner.(snyk.IssueProvider); ok { + issues = append(issues, issueProvider.IssuesForFile(file)...) } globalIssues, ok := f.documentDiagnosticCache.Load(file) if ok { @@ -532,7 +533,11 @@ func (f *Folder) getDelta(productIssueByFile snyk.ProductIssuesByFile, p product deltaSnykIssues := make([]snyk.Issue, len(diff)) for i := range diff { - deltaSnykIssues[i] = *diff[i].(*snyk.Issue) + issue, ok := diff[i].(*snyk.Issue) + if !ok { + continue + } + deltaSnykIssues[i] = *issue } productIssueByFile[p] = getIssuePerFileFromFlatList(deltaSnykIssues) diff --git a/domain/ide/workspace/folder_test.go b/domain/ide/workspace/folder_test.go index ce12a7b30..a40e6f1b7 100644 --- a/domain/ide/workspace/folder_test.go +++ b/domain/ide/workspace/folder_test.go @@ -40,6 +40,7 @@ import ( localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/mocks" "github.com/snyk/go-application-framework/pkg/workflow" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/application/config" diff --git a/domain/ide/workspace/workspace.go b/domain/ide/workspace/workspace.go index b5935cb3e..3227c194b 100644 --- a/domain/ide/workspace/workspace.go +++ b/domain/ide/workspace/workspace.go @@ -18,10 +18,11 @@ package workspace import ( "context" + "sync" + "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/domain/snyk/persistence" "github.com/snyk/snyk-ls/domain/snyk/scanner" - "sync" "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/hover" diff --git a/domain/ide/workspace/workspace_test.go b/domain/ide/workspace/workspace_test.go index 7654b881a..e2961d1f2 100644 --- a/domain/ide/workspace/workspace_test.go +++ b/domain/ide/workspace/workspace_test.go @@ -18,10 +18,11 @@ package workspace import ( "context" - "github.com/snyk/snyk-ls/domain/snyk/scanner" "testing" "time" + "github.com/snyk/snyk-ls/domain/snyk/scanner" + "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/internal/notification" diff --git a/domain/snyk/code_issue_data.go b/domain/snyk/code_issue_data.go index 89ce95180..3d74faeba 100644 --- a/domain/snyk/code_issue_data.go +++ b/domain/snyk/code_issue_data.go @@ -19,6 +19,8 @@ package snyk import ( "encoding/json" + "github.com/pkg/errors" + "github.com/snyk/snyk-ls/internal/product" ) @@ -73,5 +75,5 @@ func (c CodeIssueData) MarshalJSON() ([]byte, error) { IssueAlias: (*IssueAlias)(&c), } data, err := json.Marshal(aliasStruct) - return data, err + return data, errors.Wrap(err, "error marshaling CodeIssueData") } diff --git a/domain/snyk/persistence/file_operation.go b/domain/snyk/persistence/file_operation.go index 0931c7517..55428c6e8 100644 --- a/domain/snyk/persistence/file_operation.go +++ b/domain/snyk/persistence/file_operation.go @@ -24,6 +24,8 @@ import ( "strings" "time" + "github.com/pkg/errors" + "github.com/snyk/snyk-ls/domain/snyk" gitconfig "github.com/snyk/snyk-ls/internal/git_config" "github.com/snyk/snyk-ls/internal/product" @@ -102,7 +104,7 @@ func (g *GitPersistenceProvider) deleteFile(fullPath string) error { g.logger.Debug().Msgf("deleting cached scan file %s", fullPath) err := os.Remove(fullPath) if err != nil { - return err + return errors.Wrap(err, "failed to delete cached scan file") } return nil } diff --git a/domain/snyk/persistence/git_persistence_provider.go b/domain/snyk/persistence/git_persistence_provider.go index 4cfe79308..603afdcdc 100644 --- a/domain/snyk/persistence/git_persistence_provider.go +++ b/domain/snyk/persistence/git_persistence_provider.go @@ -26,6 +26,7 @@ import ( "sync" "github.com/rs/zerolog" + "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/util" diff --git a/domain/snyk/persistence/git_persistence_provider_test.go b/domain/snyk/persistence/git_persistence_provider_test.go index 6c6eff21c..6629b0c2b 100644 --- a/domain/snyk/persistence/git_persistence_provider_test.go +++ b/domain/snyk/persistence/git_persistence_provider_test.go @@ -17,20 +17,22 @@ package persistence import ( + "os" + "path/filepath" + "testing" + "time" + "github.com/adrg/xdg" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/object" "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/util" "github.com/snyk/snyk-ls/internal/vcs" - "github.com/stretchr/testify/assert" - "os" - "path/filepath" - "testing" - "time" ) func TestInit_Empty(t *testing.T) { diff --git a/domain/snyk/scanner/scanner_test.go b/domain/snyk/scanner/scanner_test.go index 9ea6a3622..3ce2b3c53 100644 --- a/domain/snyk/scanner/scanner_test.go +++ b/domain/snyk/scanner/scanner_test.go @@ -18,11 +18,12 @@ package scanner import ( "context" - "github.com/snyk/snyk-ls/domain/snyk" - "github.com/snyk/snyk-ls/domain/snyk/persistence" "testing" "time" + "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/domain/snyk/persistence" + "github.com/google/uuid" "github.com/stretchr/testify/assert" diff --git a/domain/snyk/scanner/test_product_scanner.go b/domain/snyk/scanner/test_product_scanner.go index efd1df6d0..ac7e4d069 100644 --- a/domain/snyk/scanner/test_product_scanner.go +++ b/domain/snyk/scanner/test_product_scanner.go @@ -18,10 +18,11 @@ package scanner import ( "context" - "github.com/snyk/snyk-ls/domain/snyk" "sync" "time" + "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/product" ) diff --git a/domain/snyk/scanner/test_scanner.go b/domain/snyk/scanner/test_scanner.go index 9c499a9a7..e7bf3b0b3 100644 --- a/domain/snyk/scanner/test_scanner.go +++ b/domain/snyk/scanner/test_scanner.go @@ -18,10 +18,11 @@ package scanner import ( "context" - "github.com/snyk/snyk-ls/domain/snyk" "sync" "time" + "github.com/snyk/snyk-ls/domain/snyk" + "github.com/google/uuid" "github.com/snyk/snyk-ls/internal/product" diff --git a/infrastructure/authentication/auth_configuration.go b/infrastructure/authentication/auth_configuration.go index 949a9b0fc..be62b03d9 100644 --- a/infrastructure/authentication/auth_configuration.go +++ b/infrastructure/authentication/auth_configuration.go @@ -23,6 +23,7 @@ import ( "github.com/snyk/go-application-framework/pkg/auth" "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/internal/storage" diff --git a/infrastructure/authentication/auth_configuration_test.go b/infrastructure/authentication/auth_configuration_test.go index 7858155ef..a377ab193 100644 --- a/infrastructure/authentication/auth_configuration_test.go +++ b/infrastructure/authentication/auth_configuration_test.go @@ -28,6 +28,7 @@ import ( "golang.org/x/oauth2" "github.com/snyk/go-application-framework/pkg/auth" + storage2 "github.com/snyk/snyk-ls/internal/storage" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/authentication/authentication_functions.go b/infrastructure/authentication/authentication_functions.go index 54ce08373..a54d0c662 100644 --- a/infrastructure/authentication/authentication_functions.go +++ b/infrastructure/authentication/authentication_functions.go @@ -23,6 +23,7 @@ import ( "github.com/snyk/go-application-framework/pkg/configuration" localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" + "github.com/snyk/snyk-ls/application/config" ) diff --git a/infrastructure/cli/cli.go b/infrastructure/cli/cli.go index b86f20691..8fe3f0261 100644 --- a/infrastructure/cli/cli.go +++ b/infrastructure/cli/cli.go @@ -31,6 +31,7 @@ import ( "github.com/snyk/go-application-framework/pkg/configuration" "github.com/snyk/go-application-framework/pkg/envvars" + "github.com/snyk/snyk-ls/application/config" noti "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/observability/error_reporting" diff --git a/infrastructure/cli/cli_extension_executor.go b/infrastructure/cli/cli_extension_executor.go index 85c723a7f..f28d15566 100644 --- a/infrastructure/cli/cli_extension_executor.go +++ b/infrastructure/cli/cli_extension_executor.go @@ -18,6 +18,7 @@ package cli import ( "context" + "fmt" "strings" "time" @@ -78,14 +79,14 @@ func (c ExtensionExecutor) doExecute(_ context.Context, cmd []string, workingDir envvars.LoadConfiguredEnvironment(legacyCLIConfig.GetStringSlice(configuration.CUSTOM_CONFIG_FILES), workingDir) data, err := engine.InvokeWithConfig(legacyCLI, legacyCLIConfig) - var output []byte if len(data) > 0 { - output = data[0].GetPayload().([]byte) - } else { - output = []byte{} + output, ok := data[0].GetPayload().([]byte) + if !ok { + return nil, fmt.Errorf("invalid response from extension executor") + } + return output, err } - - return output, err + return []byte{}, err } func (c ExtensionExecutor) ExpandParametersFromConfig(base []string) []string { diff --git a/infrastructure/cli/environment.go b/infrastructure/cli/environment.go index 400fc3803..384e8855b 100644 --- a/infrastructure/cli/environment.go +++ b/infrastructure/cli/environment.go @@ -23,6 +23,7 @@ import ( "github.com/snyk/go-application-framework/pkg/auth" "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/application/config" diff --git a/infrastructure/cli/install/discovery.go b/infrastructure/cli/install/discovery.go index cb4812d70..a4aa0fc33 100644 --- a/infrastructure/cli/install/discovery.go +++ b/infrastructure/cli/install/discovery.go @@ -36,7 +36,7 @@ type Discovery struct{} func (d *Discovery) LookPath() (string, error) { path, err := exec.LookPath(filename.ExecutableName) if err != nil { - return "", fmt.Errorf("unable to find %s in PATH: %s", filename.ExecutableName, err) + return "", fmt.Errorf("unable to find %s in PATH: %w", filename.ExecutableName, err) } return path, nil } diff --git a/infrastructure/cli/install/releases.go b/infrastructure/cli/install/releases.go index ba922649c..1e171c02b 100644 --- a/infrastructure/cli/install/releases.go +++ b/infrastructure/cli/install/releases.go @@ -30,6 +30,7 @@ import ( "github.com/pkg/errors" http2 "github.com/snyk/code-client-go/http" + "github.com/snyk/snyk-ls/application/config" ) diff --git a/infrastructure/cli/install/releases_test.go b/infrastructure/cli/install/releases_test.go index 4073df5e1..8a785eeba 100644 --- a/infrastructure/cli/install/releases_test.go +++ b/infrastructure/cli/install/releases_test.go @@ -33,6 +33,7 @@ import ( "github.com/snyk/code-client-go/http/mocks" "github.com/snyk/go-application-framework/pkg/runtimeinfo" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/code/autofix.go b/infrastructure/code/autofix.go index fe6780b25..ca247c123 100644 --- a/infrastructure/code/autofix.go +++ b/infrastructure/code/autofix.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "time" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/snyk" performance2 "github.com/snyk/snyk-ls/internal/observability/performance" diff --git a/infrastructure/code/code.go b/infrastructure/code/code.go index 5a25b430a..6c3a35a27 100644 --- a/infrastructure/code/code.go +++ b/infrastructure/code/code.go @@ -31,6 +31,7 @@ import ( codeClient "github.com/snyk/code-client-go" codeClientObservability "github.com/snyk/code-client-go/observability" "github.com/snyk/code-client-go/scan" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/application/config" diff --git a/infrastructure/code/code_error_reporter.go b/infrastructure/code/code_error_reporter.go index 95d75565e..c9756dc7f 100644 --- a/infrastructure/code/code_error_reporter.go +++ b/infrastructure/code/code_error_reporter.go @@ -18,6 +18,7 @@ package code import ( codeClient "github.com/snyk/code-client-go/observability" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" ) @@ -54,6 +55,6 @@ func newTestCodeErrorReporter() codeClient.ErrorReporter { func (s *testCodeErrorReporter) FlushErrorReporting() { } -func (s *testCodeErrorReporter) CaptureError(err error, options codeClient.ErrorReporterOptions) bool { +func (s *testCodeErrorReporter) CaptureError(_ error, _ codeClient.ErrorReporterOptions) bool { return true } diff --git a/infrastructure/code/code_html.go b/infrastructure/code/code_html.go index 8a7f6597f..dc2165985 100644 --- a/infrastructure/code/code_html.go +++ b/infrastructure/code/code_html.go @@ -21,15 +21,17 @@ import ( _ "embed" "encoding/json" "fmt" - "github.com/rs/zerolog" - "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/internal/uri" "html/template" "path/filepath" "regexp" "strings" "time" + "github.com/rs/zerolog" + + "github.com/snyk/snyk-ls/domain/ide/workspace" + "github.com/snyk/snyk-ls/internal/uri" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/html" diff --git a/infrastructure/code/code_instrumentor.go b/infrastructure/code/code_instrumentor.go index ed3f3b889..be6e49536 100644 --- a/infrastructure/code/code_instrumentor.go +++ b/infrastructure/code/code_instrumentor.go @@ -21,6 +21,7 @@ import ( "sync" codeClient "github.com/snyk/code-client-go/observability" + "github.com/snyk/snyk-ls/internal/observability/performance" ) diff --git a/infrastructure/code/code_tracker.go b/infrastructure/code/code_tracker.go index fd2e704bb..b7be6ebc9 100644 --- a/infrastructure/code/code_tracker.go +++ b/infrastructure/code/code_tracker.go @@ -21,6 +21,7 @@ import ( "github.com/rs/zerolog/log" codeClientScan "github.com/snyk/code-client-go/scan" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/progress" diff --git a/infrastructure/code/convert_test.go b/infrastructure/code/convert_test.go index 4947dc266..cb3d8a0a4 100644 --- a/infrastructure/code/convert_test.go +++ b/infrastructure/code/convert_test.go @@ -972,7 +972,7 @@ func Test_AutofixResponse_toUnifiedDiffSuggestions_HtmlEncodedFilePath(t *testin err := os.WriteFile(filepath.Join(baseDir, filePath), []byte("var x = new Array();"), 0666) require.NoError(t, err) // Here we provide the HTML encoded path and it should be decoded in the function to read the correct file. - unifiedDiffSuggestions := response.toUnifiedDiffSuggestions(baseDir, "file_with%20space.js") + unifiedDiffSuggestions := response.toUnifiedDiffSuggestions(baseDir, "file_with%20space.js") assert.Equal(t, len(unifiedDiffSuggestions), 1) assert.Equal(t, unifiedDiffSuggestions[0].FixId, "123e4567-e89b-12d3-a456-426614174000/1") diff --git a/infrastructure/code/fake_snyk_code_api_service.go b/infrastructure/code/fake_snyk_code_api_service.go index 2f1876be0..6fca2929b 100644 --- a/infrastructure/code/fake_snyk_code_api_service.go +++ b/infrastructure/code/fake_snyk_code_api_service.go @@ -143,7 +143,7 @@ type FakeSnykCodeClient struct { } func (f *FakeSnykCodeClient) GetAutofixDiffs(_ context.Context, _ string, _ AutofixOptions) (unifiedDiffSuggestions []AutofixUnifiedDiffSuggestion, status AutofixStatus, err error) { - f.AutofixStatus = AutofixStatus{message: completeStatus } + f.AutofixStatus = AutofixStatus{message: completeStatus} return f.UnifiedDiffSuggestions, f.AutofixStatus, nil } diff --git a/infrastructure/code/issue_enhancer.go b/infrastructure/code/issue_enhancer.go index 738ae7a6e..0874b41ab 100644 --- a/infrastructure/code/issue_enhancer.go +++ b/infrastructure/code/issue_enhancer.go @@ -24,6 +24,7 @@ import ( "time" codeClientObservability "github.com/snyk/code-client-go/observability" + "github.com/snyk/snyk-ls/internal/types" sglsp "github.com/sourcegraph/go-lsp" @@ -307,8 +308,13 @@ func getShardKey(folderPath string, authToken string) string { } func issueTitle(issue snyk.Issue) string { - if issue.AdditionalData != nil && issue.AdditionalData.(snyk.CodeIssueData).Title != "" { - return issue.AdditionalData.(snyk.CodeIssueData).Title + if issue.AdditionalData == nil { + return issue.ID + } + + codeIssueData, ok := issue.AdditionalData.(snyk.CodeIssueData) + if ok && codeIssueData.Title != "" { + return codeIssueData.Title } return issue.ID diff --git a/infrastructure/code/snyk_code_http_client.go b/infrastructure/code/snyk_code_http_client.go index 03bb0aba6..dfe1d22d1 100644 --- a/infrastructure/code/snyk_code_http_client.go +++ b/infrastructure/code/snyk_code_http_client.go @@ -34,6 +34,7 @@ import ( codeClientObservability "github.com/snyk/code-client-go/observability" codeClientSarif "github.com/snyk/code-client-go/sarif" + performance2 "github.com/snyk/snyk-ls/internal/observability/performance" "github.com/snyk/snyk-ls/application/config" diff --git a/infrastructure/code/snyk_code_http_client_interface.go b/infrastructure/code/snyk_code_http_client_interface.go index 6478e0fd4..d36f757b9 100644 --- a/infrastructure/code/snyk_code_http_client_interface.go +++ b/infrastructure/code/snyk_code_http_client_interface.go @@ -18,6 +18,7 @@ package code import ( "context" + "github.com/snyk/snyk-ls/domain/snyk" ) diff --git a/infrastructure/iac/iac.go b/infrastructure/iac/iac.go index 55445bd1d..e85981399 100644 --- a/infrastructure/iac/iac.go +++ b/infrastructure/iac/iac.go @@ -21,6 +21,7 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" + "errors" "fmt" "net/url" "os" @@ -33,7 +34,7 @@ import ( "github.com/snyk/snyk-ls/infrastructure/utils" "github.com/gomarkdown/markdown" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" sglsp "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" @@ -167,7 +168,7 @@ func (iac *Scanner) Scan(ctx context.Context, path string, _ string) (issues []s issues, err = iac.retrieveIssues(scanResults, issues, workspacePath) if err != nil { - return nil, errors.Wrap(err, "unable to retrieve IaC issues") + return nil, pkgerrors.Wrap(err, "unable to retrieve IaC issues") } return issues, nil @@ -183,7 +184,7 @@ func (iac *Scanner) retrieveIssues(scanResults []iacScanResult, if !isIgnored { analysisIssues, err := iac.retrieveAnalysis(s, workspacePath) if err != nil { - return nil, errors.Wrap(err, "retrieve analysis") + return nil, pkgerrors.Wrap(err, "retrieve analysis") } issues = append(issues, analysisIssues...) @@ -218,8 +219,9 @@ func (iac *Scanner) doScan(ctx context.Context, } if err != nil { - switch errorType := err.(type) { - case *exec.ExitError: + var errorType *exec.ExitError + switch { + case errors.As(err, &errorType): const iacIssuesExitCode = 1 if errorType.ExitCode() > iacIssuesExitCode { // Exit code > 1 == CLI has errors results, unmarshalErr := iac.unmarshal(res) @@ -233,10 +235,13 @@ func (iac *Scanner) doScan(ctx context.Context, return scanResults, nil // scanResults is empty } + // FIXME: no gotos! ERR: - errorOutput := string(res) + "\n\n\nSTDERR output:\n" + string(err.(*exec.ExitError).Stderr) + var exitError *exec.ExitError + errors.As(err, &exitError) + errorOutput := string(res) + "\n\n\nSTDERR output:\n" + string(exitError.Stderr) iac.c.Logger().Err(err).Str("method", method).Str("output", errorOutput).Msg("Error while calling Snyk CLI") - err = errors.Wrap(err, fmt.Sprintf("Error executing %v.\n%s", cmd, errorOutput)) + err = pkgerrors.Wrap(err, fmt.Sprintf("Error executing %v.\n%s", cmd, errorOutput)) return nil, err } default: @@ -254,14 +259,14 @@ func (iac *Scanner) unmarshal(res []byte) (scanResults []iacScanResult, err erro if strings.HasPrefix(output, "[") { if err = json.Unmarshal(res, &scanResults); err != nil { - err = errors.Wrap(err, fmt.Sprintf("Cannot unmarshal %s", output)) + err = pkgerrors.Wrap(err, fmt.Sprintf("Cannot unmarshal %s", output)) iac.c.Logger().Err(err).Str("method", method).Msg("Cannot unmarshal") return nil, err } } else { var scanResult iacScanResult if err = json.Unmarshal(res, &scanResult); err != nil { - err = errors.Wrap(err, fmt.Sprintf("Cannot unmarshal %s", output)) + err = pkgerrors.Wrap(err, fmt.Sprintf("Cannot unmarshal %s", output)) iac.c.Logger().Err(err).Str("method", method).Msg("Cannot unmarshal") return nil, err } @@ -292,7 +297,7 @@ func (iac *Scanner) retrieveAnalysis(scanResult iacScanResult, workspacePath str if err != nil { errorMessage := "Could not read file content from " + targetFile iac.c.Logger().Err(err).Msg(errorMessage) - iac.errorReporter.CaptureErrorAndReportAsIssue(workspacePath, errors.Wrap(err, errorMessage)) + iac.errorReporter.CaptureErrorAndReportAsIssue(workspacePath, pkgerrors.Wrap(err, errorMessage)) } else { fileContentString = string(rawFileContent) } @@ -309,7 +314,7 @@ func (iac *Scanner) retrieveAnalysis(scanResult iacScanResult, workspacePath str iacIssue, err := iac.toIssue(targetFile, issue, fileContentString) if err != nil { - return nil, errors.Wrap(err, "unable to convert IaC issue to Snyk issue") + return nil, pkgerrors.Wrap(err, "unable to convert IaC issue to Snyk issue") } issues = append(issues, iacIssue) @@ -370,7 +375,7 @@ func (iac *Scanner) toIssue(affectedFilePath string, issue iacIssue, fileContent additionalData, err := iac.toAdditionalData(affectedFilePath, issue) if err != nil { - return snyk.Issue{}, errors.Wrap(err, "unable to create IaC issue additional data") + return snyk.Issue{}, pkgerrors.Wrap(err, "unable to create IaC issue additional data") } result := snyk.Issue{ @@ -402,7 +407,7 @@ func (iac *Scanner) toAdditionalData(affectedFilePath string, issue iacIssue) (s iacIssuePath, err := parseIacIssuePath(issue.Path) if err != nil { - return snyk.IaCIssueData{}, errors.Wrap(err, "unable to parse IaC issue path") + return snyk.IaCIssueData{}, pkgerrors.Wrap(err, "unable to parse IaC issue path") } return snyk.IaCIssueData{ @@ -432,7 +437,7 @@ func parseIacIssuePath(path []any) ([]string, error) { case string: pathTokens = append(pathTokens, val) default: - return nil, errors.Errorf("unexpected type %T for IaC issue path token: %v", val, val) + return nil, pkgerrors.Errorf("unexpected type %T for IaC issue path token: %v", val, val) } } return pathTokens, nil @@ -450,7 +455,7 @@ func newIacCommand(codeActionTitle string, issueURL *url.URL) *types.CommandData func (iac *Scanner) createIssueURL(id string) *url.URL { parse, err := url.Parse("https://security.snyk.io/rules/cloud/" + id) if err != nil { - iac.errorReporter.CaptureError(errors.Wrap(err, "unable to create issue link for iac issue "+id)) + iac.errorReporter.CaptureError(pkgerrors.Wrap(err, "unable to create issue link for iac issue "+id)) } return parse } diff --git a/infrastructure/iac/iac_html.go b/infrastructure/iac/iac_html.go index 6a58b82e0..fd89007db 100644 --- a/infrastructure/iac/iac_html.go +++ b/infrastructure/iac/iac_html.go @@ -76,13 +76,19 @@ func (service *HtmlRenderer) GetDetailsHtml(issue snyk.Issue) string { return "" } + issueData, ok := issue.AdditionalData.(snyk.IaCIssueData) + if !ok { + service.c.Logger().Error().Msgf("Failed to parse IaC issue") + return htmlTemplate.String() + } + data := TemplateData{ Styles: getStyles(), Issue: issue, SeverityIcon: html.SeverityIcon(issue), Description: html.MarkdownToHTML(issue.Message), - Remediation: html.MarkdownToHTML(issue.AdditionalData.(snyk.IaCIssueData).Resolve), - Path: formatPath(issue.AdditionalData.(snyk.IaCIssueData).Path), + Remediation: html.MarkdownToHTML(issueData.Resolve), + Path: formatPath(issueData.Path), Nonce: template.HTML(nonce), } diff --git a/infrastructure/learn/service.go b/infrastructure/learn/service.go index ea20b4b11..dcd379648 100644 --- a/infrastructure/learn/service.go +++ b/infrastructure/learn/service.go @@ -28,6 +28,7 @@ import ( "github.com/rs/zerolog" "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/application/config" diff --git a/infrastructure/oss/cli_scanner.go b/infrastructure/oss/cli_scanner.go index 619364ffa..01e76daad 100644 --- a/infrastructure/oss/cli_scanner.go +++ b/infrastructure/oss/cli_scanner.go @@ -328,7 +328,7 @@ func (cliScanner *CLIScanner) unmarshallAndRetrieveAnalysis(ctx context.Context, targetFilePath := getAbsTargetFilePath(cliScanner.config, scanResult, workDir, path) fileContent, err := os.ReadFile(targetFilePath) if err != nil { - reportedErr := fmt.Errorf("skipping scanResult for path: %s displayTargetFile: %s in workDir: %s as we can't determine the absolute filesystem path. %v", scanResult.Path, scanResult.DisplayTargetFile, workDir, err) + reportedErr := fmt.Errorf("skipping scanResult for path: %s displayTargetFile: %s in workDir: %s as we can't determine the absolute filesystem path. %w", scanResult.Path, scanResult.DisplayTargetFile, workDir, err) cliScanner.errorReporter.CaptureErrorAndReportAsIssue(targetFilePath, reportedErr) logger.Error().Err(reportedErr).Send() continue diff --git a/infrastructure/oss/code_actions.go b/infrastructure/oss/code_actions.go index 3e62f3a26..3867f8d1e 100644 --- a/infrastructure/oss/code_actions.go +++ b/infrastructure/oss/code_actions.go @@ -118,8 +118,12 @@ func (i *ossIssue) AddQuickFixAction(affectedFilePath string, issueRange snyk.Ra return edit } - // out grouping key for oss quickfixes is the dependency name - groupingKey, groupingValue := i.getUpgradedPathParts() + // our grouping key for oss quickfixes is the dependency name + groupingKey, groupingValue, err := i.getUpgradedPathParts() + if err != nil { + logger.Warn().Err(err).Msg("could not get the upgrade path, so cannot add quickfix.") + return nil + } action, err := snyk.NewDeferredCodeAction(upgradeMessage, &autofixEditCallback, nil, types.Key(groupingKey), groupingValue) if err != nil { @@ -138,7 +142,11 @@ func (i *ossIssue) getQuickfixEdit(affectedFilePath string) string { // UpgradePath[0] is the upgrade for the package that was scanned // UpgradePath[1] is the upgrade for the root dependency - depName, depVersion := i.getUpgradedPathParts() + depName, depVersion, err := i.getUpgradedPathParts() + if err != nil { + logger.Warn().Err(err).Msg("could not get the upgrade path, so cannot add quickfix.") + return "" + } logger.Debug().Msgf("comparing %s with %s", i.UpgradePath[1], i.From[1]) // from[1] contains the package that caused this issue normalizedCurrentVersion := strings.Split(i.From[1], "@")[1] @@ -168,9 +176,13 @@ func (i *ossIssue) getQuickfixEdit(affectedFilePath string) string { return "" } -func (i *ossIssue) getUpgradedPathParts() (string, string) { - rootDependencyUpgrade := strings.Split(i.UpgradePath[1].(string), "@") +func (i *ossIssue) getUpgradedPathParts() (string, string, error) { + s, ok := i.UpgradePath[1].(string) + if !ok { + return "", "", errors.New("invalid upgrade path, could not cast to string") + } + rootDependencyUpgrade := strings.Split(s, "@") depName := strings.Join(rootDependencyUpgrade[:len(rootDependencyUpgrade)-1], "@") depVersion := rootDependencyUpgrade[len(rootDependencyUpgrade)-1] - return depName, depVersion + return depName, depVersion, nil } diff --git a/infrastructure/oss/oss_html.go b/infrastructure/oss/oss_html.go index 25f1c9568..03147db00 100644 --- a/infrastructure/oss/oss_html.go +++ b/infrastructure/oss/oss_html.go @@ -202,7 +202,10 @@ func getRemediationAdvice(issue snyk.OssIssueData) string { upgradeMessage := "" if issue.IsUpgradable || issue.IsPatchable { if hasUpgradePath { - upgradeMessage = "Upgrade to " + issue.UpgradePath[1].(string) + upgradePath, ok := issue.UpgradePath[1].(string) + if ok { + upgradeMessage = "Upgrade to " + upgradePath + } } if isOutdated { diff --git a/infrastructure/oss/types.go b/infrastructure/oss/types.go index 6b8c129cd..135908385 100644 --- a/infrastructure/oss/types.go +++ b/infrastructure/oss/types.go @@ -170,7 +170,11 @@ func (r reference) toReference() snyk.Reference { func (i *ossIssue) getUpgradeMessage() string { hasUpgradePath := len(i.UpgradePath) > 1 if hasUpgradePath { - return "Upgrade to " + i.UpgradePath[1].(string) + upgradePath, ok := i.UpgradePath[1].(string) + if !ok { + return "" + } + return "Upgrade to " + upgradePath } return "" } diff --git a/infrastructure/snyk_api/snyk_api.go b/infrastructure/snyk_api/snyk_api.go index 46d1bf840..c67ea2d6b 100644 --- a/infrastructure/snyk_api/snyk_api.go +++ b/infrastructure/snyk_api/snyk_api.go @@ -207,11 +207,11 @@ func (s *SnykApiClientImpl) doCall(method string, endpointPath string, requestBo func (s *SnykApiClientImpl) getApiResponse(caller string, path string, v interface{}) error { responseBody, err := s.doCall("GET", path, nil) if err != nil { - return fmt.Errorf("%s: %v: %v", caller, err, responseBody) + return fmt.Errorf("%s: %w: %v", caller, err, responseBody) } if err := json.Unmarshal(responseBody, v); err != nil { - return fmt.Errorf("%s: couldn't unmarshal: %v", caller, err) + return fmt.Errorf("%s: couldn't unmarshal: %w", caller, err) } return nil } diff --git a/infrastructure/utils/fingerprint.go b/infrastructure/utils/fingerprint.go index fc752d7f7..b5d603c97 100644 --- a/infrastructure/utils/fingerprint.go +++ b/infrastructure/utils/fingerprint.go @@ -19,9 +19,10 @@ package utils import ( "crypto/sha256" "fmt" - "github.com/snyk/snyk-ls/domain/snyk" "sort" "strings" + + "github.com/snyk/snyk-ls/domain/snyk" ) func CalculateFingerprintFromAdditionalData(issue snyk.Issue) string { diff --git a/internal/concurrency/atomic_map.go b/internal/concurrency/atomic_map.go deleted file mode 100644 index 49ad91789..000000000 --- a/internal/concurrency/atomic_map.go +++ /dev/null @@ -1,80 +0,0 @@ -/* - * © 2022 Snyk Limited All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package concurrency - -import ( - "sync" - "sync/atomic" -) - -type AtomicMap struct { - m sync.Map - length atomic.Value - mut sync.Mutex -} - -func (m *AtomicMap) Get(key any) any { - load, _ := m.m.Load(key) - return load -} - -func (m *AtomicMap) Contains(key any) bool { - _, ok := m.m.Load(key) - return ok -} - -func (m *AtomicMap) Length() int { - load := m.length.Load() - if load == nil { - return 0 - } - return m.length.Load().(int) -} - -func (m *AtomicMap) Put(key any, value any) { - m.mut.Lock() - if !m.Contains(key) { - m.length.Store(m.Length() + 1) - } - m.m.Store(key, value) - m.mut.Unlock() -} - -func (m *AtomicMap) ClearAll() { - m.mut.Lock() - m.length.Store(0) - m.m.Range(func(k any, _ any) bool { - m.m.Delete(k) - return true - }) - m.mut.Unlock() -} - -func (m *AtomicMap) Delete(key any) { - m.mut.Lock() - if m.Contains(key) { - m.length.Store(m.length.Load().(int) - 1) - } - m.m.Delete(key) - m.mut.Unlock() -} - -func (m *AtomicMap) Range(f func(key any, value any) bool) { - m.mut.Lock() - m.m.Range(f) - m.mut.Unlock() -} diff --git a/internal/concurrency/atomic_map_test.go b/internal/concurrency/atomic_map_test.go deleted file mode 100644 index 61451fabd..000000000 --- a/internal/concurrency/atomic_map_test.go +++ /dev/null @@ -1,103 +0,0 @@ -/* - * © 2022 Snyk Limited All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package concurrency - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestAtomicMap_ClearAll(t *testing.T) { - atomicMap := AtomicMap{} - atomicMap.Put("a", 1) - atomicMap.Put("b", 2) - - atomicMap.ClearAll() - - assert.Equal(t, 0, atomicMap.Length()) -} - -func TestAtomicMap_Contains(t *testing.T) { - atomicMap := AtomicMap{} - atomicMap.Put("a", 1) - - assert.True(t, atomicMap.Contains("a")) - assert.False(t, atomicMap.Contains("b")) -} - -func TestAtomicMap_Delete(t *testing.T) { - atomicMap := AtomicMap{} - atomicMap.Put("a", 1) - atomicMap.Put("b", 1) - - atomicMap.Delete("a") - - assert.False(t, atomicMap.Contains("a")) - assert.True(t, atomicMap.Contains("b")) - assert.Equal(t, 1, atomicMap.Length()) -} - -func TestAtomicMap_Get(t *testing.T) { - atomicMap := AtomicMap{} - atomicMap.Put("a", 1) - - assert.Equal(t, 1, atomicMap.Get("a")) -} - -func TestAtomicMap_Length(t *testing.T) { - atomicMap := AtomicMap{} - - atomicMap.Put("a", 1) - - assert.Equal(t, 1, atomicMap.Length()) - - atomicMap.Delete("a") - - assert.Equal(t, 0, atomicMap.Length()) - atomicMap.Put("a", 1) - atomicMap.Put("a", 2) - atomicMap.Put("b", 3) - - assert.Equal(t, 2, atomicMap.Length()) -} - -func TestAtomicMap_Put(t *testing.T) { - atomicMap := AtomicMap{} - - atomicMap.Put("a", 1) - - assert.Equal(t, 1, atomicMap.Get("a")) - assert.True(t, atomicMap.Contains("a")) - assert.Equal(t, 1, atomicMap.Length()) - - atomicMap.Put("b", 1) - - assert.Equal(t, 1, atomicMap.Get("a")) - assert.Equal(t, 1, atomicMap.Get("a")) - assert.True(t, atomicMap.Contains("a")) - assert.True(t, atomicMap.Contains("b")) - assert.Equal(t, 2, atomicMap.Length()) - - atomicMap.Put("b", 2) - - assert.Equal(t, 1, atomicMap.Get("a")) - assert.Equal(t, 2, atomicMap.Get("b")) - assert.True(t, atomicMap.Contains("a")) - assert.True(t, atomicMap.Contains("b")) - assert.Equal(t, 2, atomicMap.Length()) -} diff --git a/internal/delta/delta_finder_test.go b/internal/delta/delta_finder_test.go index 11e9595fc..c3f2b6440 100644 --- a/internal/delta/delta_finder_test.go +++ b/internal/delta/delta_finder_test.go @@ -17,9 +17,10 @@ package delta import ( + "testing" + "github.com/google/uuid" "golang.org/x/exp/slices" - "testing" "github.com/stretchr/testify/assert" // using testify for assertions ) diff --git a/internal/delta/fuzzy_matcher.go b/internal/delta/fuzzy_matcher.go index 64954bdd6..b06d49972 100644 --- a/internal/delta/fuzzy_matcher.go +++ b/internal/delta/fuzzy_matcher.go @@ -18,11 +18,12 @@ package delta import ( "errors" - "github.com/adrg/strutil" - "github.com/adrg/strutil/metrics" "math" "path/filepath" "strings" + + "github.com/adrg/strutil" + "github.com/adrg/strutil/metrics" ) var _ Matcher = (*FuzzyMatcher)(nil) diff --git a/internal/delta/fuzzy_matcher_test.go b/internal/delta/fuzzy_matcher_test.go index 58ddc4427..7e78819f6 100644 --- a/internal/delta/fuzzy_matcher_test.go +++ b/internal/delta/fuzzy_matcher_test.go @@ -17,10 +17,11 @@ package delta import ( + "testing" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "golang.org/x/exp/slices" - "testing" ) func Test_New_Issue(t *testing.T) { diff --git a/internal/html/nonce.go b/internal/html/nonce.go index 442431611..117bd1e22 100644 --- a/internal/html/nonce.go +++ b/internal/html/nonce.go @@ -28,7 +28,7 @@ import ( func GenerateSecurityNonce() (string, error) { nonceBytes := make([]byte, 16) if _, err := rand.Read(nonceBytes); err != nil { - return "", fmt.Errorf("error generating nonce: %v", err) + return "", fmt.Errorf("error generating nonce: %w", err) } return base64.StdEncoding.EncodeToString(nonceBytes), nil } diff --git a/internal/logging/lsp_logger.go b/internal/logging/lsp_logger.go index 7dfae205f..2c1ecfdb4 100644 --- a/internal/logging/lsp_logger.go +++ b/internal/logging/lsp_logger.go @@ -34,7 +34,7 @@ type lspWriter struct { func New(server types.Server) zerolog.LevelWriter { if server != nil { - _, _ = os.Stderr.WriteString("LSP logger: starting with non-nil server \n") + _, _ = fmt.Fprintln(os.Stderr, "LSP logger: starting with non-nil server") } readyChan := make(chan bool) writeChan := make(chan types.LogMessageParams, 1000000) @@ -45,9 +45,9 @@ func New(server types.Server) zerolog.LevelWriter { } go w.startServerSenderRoutine() // let the routine startup first - _, _ = os.Stderr.WriteString("LSP logger: waiting for ready signal... \n") + _, _ = fmt.Fprintln(os.Stderr, "LSP logger: waiting for ready signal...") <-w.readyChan - _, _ = os.Stderr.WriteString("LSP logger: started\n") + _, _ = fmt.Fprintln(os.Stderr, "LSP logger: started") return w } @@ -81,7 +81,7 @@ func (w *lspWriter) startServerSenderRoutine() { _, _ = os.Stderr.Write([]byte(msg.Message)) } } - fmt.Printf("LSP logger (%p) stopped", w) + _, _ = fmt.Fprintf(os.Stderr, "LSP logger (%p) stopped\n", w) } func mapLogLevel(level zerolog.Level) (mt types.MessageType) { diff --git a/internal/notification/notifier_mock.go b/internal/notification/notifier_mock.go index 16e45d5aa..43809c5e2 100644 --- a/internal/notification/notifier_mock.go +++ b/internal/notification/notifier_mock.go @@ -10,6 +10,8 @@ import ( "github.com/snyk/snyk-ls/internal/uri" ) +const implementMe = "implement me" + var _ Notifier = &MockNotifier{} type MockNotifier struct { @@ -23,17 +25,17 @@ type MockNotifier struct { func (m *MockNotifier) Receive() (payload any, stop bool) { //TODO implement me - panic("implement me") + panic(implementMe) } func (m *MockNotifier) CreateListener(_ func(params any)) { //TODO implement me - panic("implement me") + panic(implementMe) } func (m *MockNotifier) DisposeListener() { //TODO implement me - panic("implement me") + panic(implementMe) } func NewMockNotifier() *MockNotifier { return &MockNotifier{} } diff --git a/internal/observability/performance/noop_span.go b/internal/observability/performance/noop_span.go index be006f0ec..3225449fa 100644 --- a/internal/observability/performance/noop_span.go +++ b/internal/observability/performance/noop_span.go @@ -23,6 +23,8 @@ import ( "github.com/google/uuid" ) +const traceIdKey = "trace_id" + type NoopSpan struct { Operation string TxName string @@ -82,7 +84,7 @@ func (n *NoopSpan) GetTraceId() string { } func (n *NoopSpan) getTraceIDFromContext(ctx context.Context) (string, bool) { - t, ok := ctx.Value(TraceIdContextKey("trace_id")).(string) + t, ok := ctx.Value(TraceIdContextKey(traceIdKey)).(string) return t, ok } func (n *NoopSpan) Context() context.Context { diff --git a/internal/sdk/sdk.go b/internal/sdk/sdk.go index a760c80f1..6d7444179 100644 --- a/internal/sdk/sdk.go +++ b/internal/sdk/sdk.go @@ -25,6 +25,7 @@ import ( "github.com/subosito/gotenv" "github.com/snyk/go-application-framework/pkg/envvars" + "github.com/snyk/snyk-ls/internal/types" ) diff --git a/internal/types/command.go b/internal/types/command.go index 00b474208..c8e3b62a8 100644 --- a/internal/types/command.go +++ b/internal/types/command.go @@ -18,9 +18,10 @@ package types import ( "context" - "github.com/pkg/browser" "os" "sync" + + "github.com/pkg/browser" ) const ( diff --git a/internal/types/grouping.go b/internal/types/grouping.go index 0a6814b6a..c7273444c 100644 --- a/internal/types/grouping.go +++ b/internal/types/grouping.go @@ -16,7 +16,10 @@ package types -import "golang.org/x/mod/semver" +import ( + "github.com/rs/zerolog" + "golang.org/x/mod/semver" +) type Key string @@ -35,7 +38,7 @@ type GroupingType string const Quickfix GroupingType = "quickfix-grouping" -func MaxSemver() GroupingFunction { +func MaxSemver(logger zerolog.Logger) GroupingFunction { return func(groupables []Groupable) any { if len(groupables) == 0 { return nil @@ -54,8 +57,13 @@ func MaxSemver() GroupingFunction { chosenGroupable = groupable } - chosenVersion := "v" + chosenGroupable.GetGroupingValue().(string) + group, ok := chosenGroupable.GetGroupingValue().(string) + if !ok { + logger.Debug().Msgf("could not cast first groupable value %v to string, skipping", chosenGroupable.GetGroupingValue()) + continue + } + chosenVersion := "v" + group if semver.Compare(chosenVersion, currentVersion) < 0 { chosenGroupable = groupable } diff --git a/internal/vcs/git_cloner.go b/internal/vcs/git_cloner.go index f70cbbac9..a44d87a63 100644 --- a/internal/vcs/git_cloner.go +++ b/internal/vcs/git_cloner.go @@ -17,13 +17,14 @@ package vcs import ( + "path/filepath" + "strings" + "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" "github.com/otiai10/copy" "github.com/rs/zerolog" - "path/filepath" - "strings" ) func Clone(logger *zerolog.Logger, srcRepoPath string, destinationPath string, targetBranchName string) (*git.Repository, error) { diff --git a/internal/vcs/git_cloner_test.go b/internal/vcs/git_cloner_test.go index f28d61d5a..ffed8c9f1 100644 --- a/internal/vcs/git_cloner_test.go +++ b/internal/vcs/git_cloner_test.go @@ -17,15 +17,17 @@ package vcs import ( + "os" + "path/filepath" + "testing" + "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" - "github.com/snyk/snyk-ls/internal/testutil" "github.com/stretchr/testify/assert" - "os" - "path/filepath" - "testing" + + "github.com/snyk/snyk-ls/internal/testutil" ) func TestClone_ShouldClone(t *testing.T) { diff --git a/internal/vcs/git_utils.go b/internal/vcs/git_utils.go index 2754163d0..eb493290a 100644 --- a/internal/vcs/git_utils.go +++ b/internal/vcs/git_utils.go @@ -17,12 +17,14 @@ package vcs import ( + "regexp" + "strings" + "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/rs/zerolog" + gitconfig "github.com/snyk/snyk-ls/internal/git_config" - "regexp" - "strings" ) var ( diff --git a/ls_extension/main.go b/ls_extension/main.go index bd0c8be89..6c08eac59 100644 --- a/ls_extension/main.go +++ b/ls_extension/main.go @@ -89,11 +89,11 @@ func lsWorkflow( config.SetCurrentConfig(c) if extensionConfig.GetBool("v") { - fmt.Println(config.Version) + fmt.Println(config.Version) //nolint:forbidigo // we want to output the version to stdout here return output, err } else if extensionConfig.GetBool("licenses") { about, err := cli.NewExtensionExecutor(c).Execute(context.Background(), []string{"snyk", "--about"}, "") - fmt.Println(string(about)) + fmt.Println(string(about)) //nolint:forbidigo // we want to output licenses to stdout here return output, err } else { diff --git a/main.go b/main.go index bbf78e5f3..1bade8dd4 100644 --- a/main.go +++ b/main.go @@ -45,7 +45,7 @@ func main() { c := config.CurrentConfig() output, err := parseFlags(os.Args, c) if err != nil { - fmt.Println(err, output) + fmt.Println(err, output) //nolint:forbidigo // we want to output to stdout here os.Exit(1) } if output != "" { diff --git a/main_test.go b/main_test.go index d57637b30..813c5a25d 100644 --- a/main_test.go +++ b/main_test.go @@ -17,7 +17,6 @@ package main import ( - "fmt" "os" "path/filepath" "strings" @@ -98,11 +97,9 @@ func Test_ConfigureLoggingShouldAddFileLogger(t *testing.T) { assert.Eventuallyf(t, func() bool { bytes, err := os.ReadFile(config.CurrentConfig().LogPath()) - fmt.Println("Read file " + config.CurrentConfig().LogPath()) if err != nil { return false } - fmt.Println("Read bytes:" + string(bytes)) // no logger usage here return len(bytes) > 0 }, 2*time.Second, 10*time.Millisecond, "didn't write to logfile") }