Skip to content

project_detector

Full name: tenets.core.analysis.project_detector

project_detector

Project type detection and entry point discovery.

This module provides intelligent detection of project types, main entry points, and project structure based on language analyzers and file patterns.

Classes

ProjectDetector

Python
ProjectDetector()

Detects project type and structure using language analyzers.

This class leverages the language-specific analyzers to detect project types and entry points, avoiding duplication of language-specific knowledge.

Initialize project detector with language analyzers.

Source code in tenets/core/analysis/project_detector.py
Python
def __init__(self):
    """Initialize project detector with language analyzers."""
    self.logger = get_logger(__name__)

    # Initialize all language analyzers
    self.analyzers = [
        PythonAnalyzer(),
        JavaScriptAnalyzer(),
        JavaAnalyzer(),
        GoAnalyzer(),
        RustAnalyzer(),
        CppAnalyzer(),
        CSharpAnalyzer(),
        RubyAnalyzer(),
        PhpAnalyzer(),
        SwiftAnalyzer(),
        KotlinAnalyzer(),
        ScalaAnalyzer(),
        DartAnalyzer(),
        GDScriptAnalyzer(),
        HTMLAnalyzer(),
        CSSAnalyzer(),
    ]

    # Build dynamic mappings from analyzers
    self._build_mappings()

    # Additional framework patterns not tied to specific languages
    self.FRAMEWORK_PATTERNS = {
        "docker": ["Dockerfile", "docker-compose.yml", "docker-compose.yaml"],
        "kubernetes": ["k8s/", "kubernetes/", "deployment.yaml", "service.yaml"],
        "terraform": ["*.tf", "terraform.tfvars"],
        "ansible": ["ansible.cfg", "playbook.yml", "inventory"],
        "ci_cd": [".github/workflows/", ".gitlab-ci.yml", "Jenkinsfile", ".travis.yml"],
    }
Functions
detect_project_type
Python
detect_project_type(path: Path) -> Dict[str, any]

Detect project type and main entry points.

PARAMETERDESCRIPTION
path

Root directory to analyze

TYPE:Path

RETURNSDESCRIPTION
Dict[str, any]

Dictionary containing: - type: Primary project type - languages: List of detected languages - frameworks: List of detected frameworks - entry_points: List of likely entry point files - confidence: Confidence score (0-1)

Source code in tenets/core/analysis/project_detector.py
Python
def detect_project_type(self, path: Path) -> Dict[str, any]:
    """Detect project type and main entry points.

    Args:
        path: Root directory to analyze

    Returns:
        Dictionary containing:
            - type: Primary project type
            - languages: List of detected languages
            - frameworks: List of detected frameworks
            - entry_points: List of likely entry point files
            - confidence: Confidence score (0-1)
    """
    path = Path(path)
    if not path.exists():
        return {
            "type": "unknown",
            "languages": [],
            "frameworks": [],
            "entry_points": [],
            "confidence": 0.0,
        }

    # Collect all files
    all_files = []
    for ext in ["*.*", "Dockerfile", "Makefile", "Jenkinsfile"]:
        all_files.extend(path.rglob(ext))

    # Analyze file extensions to detect languages
    extensions = Counter()
    for file in all_files:
        if file.is_file():
            ext = file.suffix.lower()
            if ext:
                extensions[ext] += 1

    # Determine primary languages based on extensions
    languages = []
    for ext, count in extensions.most_common(10):
        if ext in self.EXTENSION_TO_LANGUAGE:
            lang = self.EXTENSION_TO_LANGUAGE[ext]
            if lang not in languages:
                languages.append(lang)

    # Detect frameworks based on indicators
    frameworks = []
    file_names = {f.name for f in all_files if f.is_file()}
    dir_names = {f.name for f in all_files if f.is_dir()}

    # Check language-specific project indicators
    for project_type, indicators in self.PROJECT_INDICATORS.items():
        for indicator in indicators:
            if indicator in file_names or indicator in dir_names:
                frameworks.append(project_type)
                break

    # Check general framework patterns
    for framework, patterns in self.FRAMEWORK_PATTERNS.items():
        for pattern in patterns:
            if pattern.endswith("/"):
                # Directory pattern
                if pattern[:-1] in dir_names:
                    frameworks.append(framework)
                    break
            elif "*" in pattern:
                # Glob pattern
                if any(f.match(pattern) for f in all_files if f.is_file()):
                    frameworks.append(framework)
                    break
            else:
                # File pattern
                if pattern in file_names:
                    frameworks.append(framework)
                    break

    # Find entry points
    entry_points = self._find_entry_points(path, languages, file_names)

    # Determine primary project type
    project_type = self._determine_project_type(languages, frameworks)

    # Calculate confidence
    confidence = self._calculate_confidence(languages, frameworks, entry_points)

    return {
        "type": project_type,
        "languages": languages[:3],  # Top 3 languages
        "frameworks": list(set(frameworks))[:3],  # Top 3 unique frameworks
        "entry_points": entry_points[:5],  # Top 5 entry points
        "confidence": confidence,
    }
find_main_file
Python
find_main_file(path: Path) -> Optional[Path]

Find the most likely main/entry file in a project.

PARAMETERDESCRIPTION
path

Directory to search in

TYPE:Path

RETURNSDESCRIPTION
Optional[Path]

Path to the main file, or None if not found

Source code in tenets/core/analysis/project_detector.py
Python
def find_main_file(self, path: Path) -> Optional[Path]:
    """Find the most likely main/entry file in a project.

    Args:
        path: Directory to search in

    Returns:
        Path to the main file, or None if not found
    """
    path = Path(path)
    if not path.is_dir():
        return None

    # Detect project info
    project_info = self.detect_project_type(path)

    # Use detected entry points
    if project_info["entry_points"]:
        main_file = path / project_info["entry_points"][0]
        if main_file.exists():
            return main_file

    # Fall back to language-specific patterns
    for lang in project_info["languages"]:
        if lang in self.ENTRY_POINTS:
            for entry_point in self.ENTRY_POINTS[lang]:
                for file_path in path.rglob(entry_point):
                    if file_path.is_file():
                        return file_path

    return None

Functions