Class: Sxn::Rules::ProjectDetector
- Inherits:
-
Object
- Object
- Sxn::Rules::ProjectDetector
- Defined in:
- lib/sxn/rules/project_detector.rb
Overview
ProjectDetector analyzes project directories to determine their type, language, package manager, and suggests appropriate default rules for project setup.
Constant Summary collapse
- PROJECT_TYPES =
Project type definitions with their detection criteria
{ rails: { files: %w[Gemfile config/application.rb], patterns: { gemfile_contains: ["rails"] }, confidence: :high }, ruby: { files: %w[Gemfile *.gemspec], patterns: {}, confidence: :medium }, nextjs: { files: %w[package.json next.config.js], patterns: { package_json_deps: ["next"] }, confidence: :high }, react: { files: %w[package.json], patterns: { package_json_deps: ["react"] }, confidence: :high }, nodejs: { files: %w[package.json], patterns: { package_json_deps: ["express", "fastify", "koa", "@types/node", "nodemon", "typescript"] }, confidence: :medium_high }, javascript: { files: %w[package.json], patterns: {}, confidence: :medium }, typescript: { files: %w[tsconfig.json *.ts], patterns: {}, confidence: :high }, python: { files: %w[requirements.txt setup.py pyproject.toml Pipfile], patterns: {}, confidence: :medium }, django: { files: %w[manage.py], patterns: { requirements_contains: ["django"] }, confidence: :high }, go: { files: %w[go.mod go.sum *.go], patterns: {}, confidence: :high }, rust: { files: %w[Cargo.toml Cargo.lock], patterns: {}, confidence: :high } }.freeze
- PACKAGE_MANAGERS =
Package manager detection patterns
{ bundler: { files: %w[Gemfile Gemfile.lock], command: "bundle" }, npm: { files: %w[package-lock.json], command: "npm" }, yarn: { files: %w[yarn.lock], command: "yarn" }, pnpm: { files: %w[pnpm-lock.yaml], command: "pnpm" }, pip: { files: %w[requirements.txt], command: "pip" }, pipenv: { files: %w[Pipfile Pipfile.lock], command: "pipenv" }, poetry: { files: %w[pyproject.toml poetry.lock], command: "poetry" }, cargo: { files: %w[Cargo.toml Cargo.lock], command: "cargo" }, go_mod: { files: %w[go.mod go.sum], command: "go" } }.freeze
Instance Attribute Summary collapse
-
#project_path ⇒ Object
readonly
Returns the value of attribute project_path.
Instance Method Summary collapse
-
#analyze_project_structure ⇒ Hash
Get detailed analysis of the project structure.
-
#detect_package_manager ⇒ Symbol
Detect the package manager used by the project.
-
#detect_project_info ⇒ Hash
Detect comprehensive project information.
-
#detect_project_type ⇒ Symbol
Legacy method for compatibility with tests Detect the primary project type.
-
#detect_type(path) ⇒ Symbol
Detect project type for a given path (used by ConfigManager).
-
#initialize(project_path) ⇒ ProjectDetector
constructor
Initialize the project detector.
-
#suggest_default_rules ⇒ Hash
Suggest default rules based on detected project characteristics.
Constructor Details
#initialize(project_path) ⇒ ProjectDetector
Initialize the project detector
136 137 138 139 140 141 142 143 |
# File 'lib/sxn/rules/project_detector.rb', line 136 def initialize(project_path) raise ArgumentError, "Project path cannot be nil or empty" if project_path.nil? || project_path.empty? @project_path = File.realpath(project_path) validate_project_path! rescue Errno::ENOENT raise ArgumentError, "Project path does not exist: #{project_path}" end |
Instance Attribute Details
#project_path ⇒ Object (readonly)
Returns the value of attribute project_path.
131 132 133 |
# File 'lib/sxn/rules/project_detector.rb', line 131 def project_path @project_path end |
Instance Method Details
#analyze_project_structure ⇒ Hash
Get detailed analysis of the project structure
245 246 247 248 249 250 251 252 253 254 |
# File 'lib/sxn/rules/project_detector.rb', line 245 def analyze_project_structure { files: analyze_important_files, directories: analyze_directory_structure, dependencies: analyze_dependencies, configuration: analyze_configuration_files, scripts: analyze_scripts, documentation: analyze_documentation } end |
#detect_package_manager ⇒ Symbol
Detect the package manager used by the project
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/sxn/rules/project_detector.rb', line 197 def detect_package_manager PACKAGE_MANAGERS.each do |manager, criteria| return manager if criteria[:files].any? { |file| file_exists_in_project?(file) } end # Fallback logic for common scenarios if file_exists_in_project?("package.json") return :npm # Default to npm for Node.js projects without specific lock files end if file_exists_in_project?("Gemfile") return :bundler # Default to bundler for Ruby projects without lock files end :unknown end |
#detect_project_info ⇒ Hash
Detect comprehensive project information
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/sxn/rules/project_detector.rb', line 148 def detect_project_info { type: detect_project_type, language: detect_primary_language, languages: detect_all_languages, package_manager: detect_package_manager, framework: detect_framework, has_docker: has_docker?, has_tests: has_tests?, has_ci: has_ci_config?, database: detect_database, sensitive_files: detect_sensitive_files, analysis_timestamp: Time.now.iso8601 } end |
#detect_project_type ⇒ Symbol
Legacy method for compatibility with tests Detect the primary project type
182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/sxn/rules/project_detector.rb', line 182 def detect_project_type detected_types = [] PROJECT_TYPES.each do |type, criteria| confidence = calculate_type_confidence(type, criteria) detected_types << { type: type, confidence: confidence } if confidence.positive? end # Sort by confidence and return the highest detected_types.min_by { |t| -t[:confidence] }&.fetch(:type) || :unknown end |
#detect_type(path) ⇒ Symbol
Detect project type for a given path (used by ConfigManager)
168 169 170 171 172 173 174 175 176 |
# File 'lib/sxn/rules/project_detector.rb', line 168 def detect_type(path) old_path = @project_path @project_path = File.realpath(path) result = detect_project_type @project_path = old_path result rescue Errno::ENOENT :unknown end |
#suggest_default_rules ⇒ Hash
Suggest default rules based on detected project characteristics
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/sxn/rules/project_detector.rb', line 217 def suggest_default_rules project_info = detect_project_info rules = {} # Add copy files rules based on project type copy_files = suggest_copy_files_rules(project_info) rules["copy_files"] = copy_files unless copy_files["config"]["files"] && copy_files["config"]["files"].empty? # Add setup commands rules based on package manager setup_commands = suggest_setup_commands_rules(project_info) unless setup_commands["config"]["commands"] && setup_commands["config"]["commands"].empty? rules["setup_commands"] = setup_commands end # Add template rules for common project documentation template_rules = suggest_template_rules(project_info) unless template_rules["config"]["templates"] && template_rules["config"]["templates"].empty? rules["templates"] = template_rules end rules end |