internal/platform/commoncontext/native.go (113 lines of code) (raw):

/* * Copyright 2021-2024 JetBrains s.r.o. * * 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 * * https://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 commoncontext // currently contains only the logic for .NET products import ( "bufio" "os" "path/filepath" "strings" "sync" "github.com/JetBrains/qodana-cli/internal/platform/product" log "github.com/sirupsen/logrus" ) func isNativeRequired(projectDir string, linter product.Linter) bool { if linter != product.DotNetLinter { return false } return containsUnityProjects(projectDir) || containsDotNetFxProjects(projectDir) } func containsUnityProjects(projectDir string) bool { assetsPath := filepath.Join(projectDir, "Assets") projectSettingsPath := filepath.Join(projectDir, "ProjectSettings") if !isDirectory(assetsPath) { return false } if !isDirectory(projectSettingsPath) { return false } isUnityProject := false err := filepath.Walk( projectSettingsPath, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.Name() == "ProjectVersion.txt" || strings.ToLower(filepath.Ext(path)) == ".asset" { isUnityProject = true } return nil }, ) if err != nil { return isUnityProject } return isUnityProject } func isDirectory(path string) bool { info, err := os.Stat(path) if err != nil { return false } return info.IsDir() } func containsDotNetFxProjects(projectDir string) bool { var found = false var waitGroup sync.WaitGroup var mutex = &sync.Mutex{} err := filepath.Walk( projectDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } isFound := false mutex.Lock() isFound = found mutex.Unlock() if info.IsDir() || filepath.Ext(path) != ".csproj" || isFound { return nil } waitGroup.Add(1) go func(path string) { defer waitGroup.Done() match, err := checkFile(path) if err != nil { return } if match { mutex.Lock() found = true mutex.Unlock() } }(path) return nil }, ) if err != nil { return false } waitGroup.Wait() return found } func checkFile(path string) (bool, error) { file, err := os.Open(path) if err != nil { return false, err } defer func(file *os.File) { err := file.Close() if err != nil { log.Error(err) } }(file) scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() if strings.Contains(line, "<TargetFramework") && (strings.Contains(line, "net4") || strings.Contains( line, "v4", )) { return true, nil } } if err := scanner.Err(); err != nil { return false, err } return false, nil }