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
}