476 lines
16 KiB
C#
Executable File
476 lines
16 KiB
C#
Executable File
using System;
|
|
using System.Linq;
|
|
|
|
namespace MarketAlly.ProjectDetector.Detectors;
|
|
|
|
public class FunctionAppProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// Azure Functions packages
|
|
var functionPackages = new[]
|
|
{
|
|
"Microsoft.NET.Sdk.Functions", "Microsoft.Azure.Functions.Worker",
|
|
"Microsoft.Azure.WebJobs", "Microsoft.Azure.WebJobs.Extensions"
|
|
};
|
|
|
|
if (functionPackages.Any(pkg => analysis.PackageReferences.Any(p => p.Contains(pkg))))
|
|
{
|
|
confidence += 60;
|
|
reasons.Add("Has Azure Functions packages");
|
|
}
|
|
|
|
// Function app files
|
|
if (analysis.Files.Any(f => f.Equals("host.json", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 30;
|
|
reasons.Add("Contains host.json");
|
|
}
|
|
|
|
if (analysis.Files.Any(f => f.Equals("local.settings.json", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 20;
|
|
reasons.Add("Contains local.settings.json");
|
|
}
|
|
|
|
// Function attributes in code
|
|
if (analysis.Files.Any(f => f.EndsWith(".cs", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 15;
|
|
reasons.Add("Contains C# files (potential functions)");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 50,
|
|
ProjectType = ProjectType.Function,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class SharedProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// Shared project file
|
|
if (analysis.Files.Any(f => f.EndsWith(".shproj", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 80;
|
|
reasons.Add("Contains shared project file (.shproj)");
|
|
}
|
|
|
|
// Shared project items
|
|
if (analysis.Files.Any(f => f.EndsWith(".projitems", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 60;
|
|
reasons.Add("Contains shared project items file");
|
|
}
|
|
|
|
// Common shared project naming
|
|
var sharedKeywords = new[] { "shared", "common", "core" };
|
|
if (sharedKeywords.Any(keyword => analysis.Files.Any(f =>
|
|
f.Contains(keyword, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 20;
|
|
reasons.Add("Contains shared/common naming patterns");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 60,
|
|
ProjectType = ProjectType.SharedProject,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class ToolProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// .NET Tool packages
|
|
if (analysis.HasCommandLine)
|
|
{
|
|
confidence += 40;
|
|
reasons.Add("Has command line packages");
|
|
}
|
|
|
|
// Tool-specific properties
|
|
if (analysis.OutputType.Equals("Exe", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
confidence += 30;
|
|
reasons.Add("Executable output type");
|
|
}
|
|
|
|
// Tool naming patterns
|
|
var toolKeywords = new[] { "tool", "cli", "command", "utility" };
|
|
if (toolKeywords.Any(keyword => analysis.Files.Any(f =>
|
|
f.Contains(keyword, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 25;
|
|
reasons.Add("Contains tool-related naming");
|
|
}
|
|
|
|
// Global tool configuration
|
|
if (analysis.Files.Any(f => f.Contains("PackAsTool") || f.Contains("ToolCommandName")))
|
|
{
|
|
confidence += 35;
|
|
reasons.Add("Has global tool configuration");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 40,
|
|
ProjectType = ProjectType.Tool,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class PluginProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// Plugin frameworks
|
|
if (analysis.HasPluginFramework)
|
|
{
|
|
confidence += 30;
|
|
reasons.Add("Has plugin framework packages");
|
|
}
|
|
|
|
// Plugin naming patterns
|
|
var pluginKeywords = new[] { "plugin", "extension", "addon", "module" };
|
|
if (pluginKeywords.Any(keyword => analysis.Files.Any(f =>
|
|
f.Contains(keyword, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 35;
|
|
reasons.Add("Contains plugin-related naming");
|
|
}
|
|
|
|
// Plugin interfaces
|
|
if (analysis.Files.Any(f => f.Contains("IPlugin") || f.Contains("IExtension")))
|
|
{
|
|
confidence += 25;
|
|
reasons.Add("Contains plugin interfaces");
|
|
}
|
|
|
|
// Library output (plugins are typically libraries)
|
|
if (analysis.IsLibrary)
|
|
{
|
|
confidence += 20;
|
|
reasons.Add("Library output type");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 40,
|
|
ProjectType = ProjectType.Plugin,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class InfrastructureProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// Infrastructure as Code packages
|
|
if (analysis.HasInfrastructure)
|
|
{
|
|
confidence += 60;
|
|
reasons.Add("Has infrastructure packages");
|
|
}
|
|
|
|
// Infrastructure files
|
|
var infraFiles = new[] { "terraform", "pulumi", "cdk.json", "cloudformation" };
|
|
if (infraFiles.Any(file => analysis.Files.Any(f =>
|
|
f.Contains(file, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 40;
|
|
reasons.Add("Contains infrastructure files");
|
|
}
|
|
|
|
// Infrastructure folders
|
|
var infraFolders = new[] { "terraform", "infrastructure", "infra", "deployment", "provisioning" };
|
|
if (infraFolders.Any(folder => analysis.Folders.Any(f =>
|
|
f.Contains(folder, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 30;
|
|
reasons.Add("Contains infrastructure folders");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 50,
|
|
ProjectType = ProjectType.Infrastructure,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class ChatBotProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// Bot Framework packages
|
|
var botPackages = new[]
|
|
{
|
|
"Microsoft.Bot.Builder", "Microsoft.Bot.Schema", "Microsoft.Bot.Connector",
|
|
"BotBuilder", "Telegram.Bot", "Discord.Net", "SlackNet"
|
|
};
|
|
|
|
if (botPackages.Any(pkg => analysis.PackageReferences.Any(p => p.Contains(pkg))))
|
|
{
|
|
confidence += 60;
|
|
reasons.Add("Has bot framework packages");
|
|
}
|
|
|
|
// AI/ML packages (often used in chatbots)
|
|
var aiPackages = new[]
|
|
{
|
|
"Microsoft.ML", "TensorFlow", "OpenAI", "Azure.AI.OpenAI",
|
|
"Microsoft.SemanticKernel", "LangChain"
|
|
};
|
|
|
|
if (aiPackages.Any(pkg => analysis.PackageReferences.Any(p => p.Contains(pkg))))
|
|
{
|
|
confidence += 30;
|
|
reasons.Add("Has AI/ML packages");
|
|
}
|
|
|
|
// Bot-related files
|
|
var botKeywords = new[] { "bot", "chat", "conversation", "dialog", "luis", "qna" };
|
|
if (botKeywords.Any(keyword => analysis.Files.Any(f =>
|
|
f.Contains(keyword, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 25;
|
|
reasons.Add("Contains bot-related files");
|
|
}
|
|
|
|
// Node.js bot packages
|
|
var nodeBotPackages = new[] { "botbuilder", "botframework", "telegraf", "discord.js" };
|
|
if (nodeBotPackages.Any(pkg => analysis.PackageJsonDependencies.ContainsKey(pkg) ||
|
|
analysis.PackageJsonDevDependencies.ContainsKey(pkg)))
|
|
{
|
|
confidence += 50;
|
|
reasons.Add("Has Node.js bot packages");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 70, // Higher threshold for chatbot
|
|
ProjectType = ProjectType.ChatBot,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class WorkflowProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// Azure Functions packages (primary workflow indicator)
|
|
if (analysis.HasAzureFunctions)
|
|
{
|
|
confidence += 70;
|
|
reasons.Add("Has Azure Functions packages");
|
|
}
|
|
|
|
// Azure Logic Apps and workflow packages
|
|
var workflowPackages = new[]
|
|
{
|
|
"Microsoft.Azure.Workflows", "Microsoft.Azure.Management.Logic",
|
|
"Microsoft.Azure.ServiceBus", "Microsoft.Azure.EventGrid",
|
|
"Microsoft.Azure.EventHubs"
|
|
};
|
|
|
|
if (workflowPackages.Any(pkg => analysis.PackageReferences.Any(p => p.Contains(pkg))))
|
|
{
|
|
confidence += 60;
|
|
reasons.Add("Has Azure workflow packages");
|
|
}
|
|
|
|
// Workflow automation frameworks
|
|
var automationPackages = new[]
|
|
{
|
|
"Hangfire", "Quartz", "Microsoft.Extensions.Hosting.BackgroundService",
|
|
"Workflow.Core", "Elsa", "Orleans"
|
|
};
|
|
|
|
if (automationPackages.Any(pkg => analysis.PackageReferences.Any(p => p.Contains(pkg))))
|
|
{
|
|
confidence += 50;
|
|
reasons.Add("Has workflow automation packages");
|
|
}
|
|
|
|
// Function app configuration files
|
|
if (analysis.Files.Any(f => f.Equals("host.json", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 40;
|
|
reasons.Add("Contains Azure Functions host.json");
|
|
}
|
|
|
|
if (analysis.Files.Any(f => f.Equals("local.settings.json", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 30;
|
|
reasons.Add("Contains Azure Functions local settings");
|
|
}
|
|
|
|
// Workflow-specific files and naming
|
|
var workflowKeywords = new[] { "workflow", "function", "trigger", "orchestrator", "activity" };
|
|
if (workflowKeywords.Any(keyword => analysis.Files.Any(f =>
|
|
f.Contains(keyword, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 25;
|
|
reasons.Add("Contains workflow-related files");
|
|
}
|
|
|
|
// Serverless framework files (Node.js)
|
|
if (analysis.Files.Any(f => f.Equals("serverless.yml", StringComparison.OrdinalIgnoreCase) ||
|
|
f.Equals("serverless.yaml", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 50;
|
|
reasons.Add("Contains Serverless framework configuration");
|
|
}
|
|
|
|
// AWS Lambda indicators
|
|
var lambdaPackages = new[] { "Amazon.Lambda.Core", "Amazon.Lambda.Serialization.Json" };
|
|
if (lambdaPackages.Any(pkg => analysis.PackageReferences.Any(p => p.Contains(pkg))))
|
|
{
|
|
confidence += 60;
|
|
reasons.Add("Has AWS Lambda packages");
|
|
}
|
|
|
|
// Node.js serverless packages
|
|
var nodeServerlessPackages = new[] { "serverless", "aws-lambda", "azure-functions-core-tools" };
|
|
if (nodeServerlessPackages.Any(pkg => analysis.PackageJsonDependencies.ContainsKey(pkg) ||
|
|
analysis.PackageJsonDevDependencies.ContainsKey(pkg)))
|
|
{
|
|
confidence += 50;
|
|
reasons.Add("Has Node.js serverless packages");
|
|
}
|
|
|
|
// Python serverless packages
|
|
var pythonServerlessPackages = new[] { "azure-functions", "aws-lambda-runtime", "chalice" };
|
|
if (pythonServerlessPackages.Any(pkg => analysis.PythonRequirements.Any(req =>
|
|
req.ToLowerInvariant().Contains(pkg))))
|
|
{
|
|
confidence += 50;
|
|
reasons.Add("Has Python serverless packages");
|
|
}
|
|
|
|
// Workflow orchestration folders
|
|
var workflowFolders = new[] { "functions", "workflows", "orchestrators", "activities", "triggers" };
|
|
if (workflowFolders.Any(folder => analysis.Folders.Any(f =>
|
|
f.Contains(folder, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 20;
|
|
reasons.Add("Contains workflow orchestration structure");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 50,
|
|
ProjectType = ProjectType.Workflow,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class ContainerProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
var confidence = 0;
|
|
var reasons = new List<string>();
|
|
|
|
// Docker files
|
|
if (analysis.Files.Any(f => f.Equals("Dockerfile", StringComparison.OrdinalIgnoreCase) ||
|
|
f.Equals("docker-compose.yml", StringComparison.OrdinalIgnoreCase) ||
|
|
f.Equals("docker-compose.yaml", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
confidence += 70;
|
|
reasons.Add("Contains Docker configuration files");
|
|
}
|
|
|
|
// Container orchestration files
|
|
var k8sFiles = new[] { "deployment.yaml", "deployment.yml", "kubernetes.yaml", "k8s.yaml", "helm" };
|
|
if (k8sFiles.Any(file => analysis.Files.Any(f =>
|
|
f.Contains(file, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 40;
|
|
reasons.Add("Contains Kubernetes/orchestration files");
|
|
}
|
|
|
|
// Container-related folders
|
|
var containerFolders = new[] { ".docker", "docker", "k8s", "kubernetes", "charts" };
|
|
if (containerFolders.Any(folder => analysis.Folders.Any(f =>
|
|
f.Equals(folder, StringComparison.OrdinalIgnoreCase))))
|
|
{
|
|
confidence += 30;
|
|
reasons.Add("Contains container-related folders");
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = confidence >= 50,
|
|
ProjectType = ProjectType.ContainerApp,
|
|
Confidence = Math.Min(confidence, 100),
|
|
Reason = string.Join(", ", reasons)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class SolutionProjectDetector : IProjectTypeDetector
|
|
{
|
|
public ProjectTypeDetectionResult Detect(ProjectAnalysis analysis)
|
|
{
|
|
if (analysis.HasSolutionFile)
|
|
{
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = true,
|
|
ProjectType = ProjectType.Solution,
|
|
Confidence = 100,
|
|
Reason = "Is a solution file"
|
|
};
|
|
}
|
|
|
|
return new ProjectTypeDetectionResult
|
|
{
|
|
IsMatch = false,
|
|
ProjectType = ProjectType.Other,
|
|
Confidence = 0,
|
|
Reason = "Not a solution"
|
|
};
|
|
}
|
|
} |