<commit_before>package com.redhat.ceylon.eclipse.core.builder;

import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getPackage;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectModelLoader;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getRootFolder;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.isInSourceFolder;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.isResourceFile;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.isSourceFile;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;

import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleManager;
import com.redhat.ceylon.compiler.typechecker.model.Package;
import com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.BooleanHolder;
import com.redhat.ceylon.eclipse.core.model.IResourceAware;
import com.redhat.ceylon.eclipse.core.model.ProjectSourceFile;
import com.redhat.ceylon.eclipse.ui.ceylon.model.delta.CompilationUnitDelta;

final class DeltaScanner implements IResourceDeltaVisitor {
    private final BooleanHolder mustDoFullBuild;
    private final IProject project;
    private final BooleanHolder somethingToBuild;
    private final BooleanHolder mustResolveClasspathContainer;
	private IPath explodedDirPath;
	private Map<IProject, IPath> modulesDirPathByProject = new HashMap<>();
	private boolean astAwareIncrementalBuild = true;
	
    DeltaScanner(BooleanHolder mustDoFullBuild, IProject project,
            BooleanHolder somethingToBuild,
            BooleanHolder mustResolveClasspathContainer) {
        this.mustDoFullBuild = mustDoFullBuild;
        this.project = project;
        this.somethingToBuild = somethingToBuild;
        this.mustResolveClasspathContainer = mustResolveClasspathContainer;
        IFolder explodedFolder = CeylonBuilder.getCeylonClassesOutputFolder(project);
        explodedDirPath = explodedFolder != null ? explodedFolder.getFullPath() : null;
        IFolder modulesFolder = CeylonBuilder.getCeylonModulesOutputFolder(project);
        IPath modulesDirPath = modulesFolder != null ? modulesFolder.getFullPath() : null;
        modulesDirPathByProject.put(project, modulesDirPath);
        try {
			for (IProject referencedProject : project.getReferencedProjects()) {
		        modulesFolder = CeylonBuilder.getCeylonModulesOutputFolder(referencedProject);
		        modulesDirPath = modulesFolder != null ? modulesFolder.getFullPath() : null;
		        modulesDirPathByProject.put(referencedProject, modulesDirPath);
			}
		} catch (CoreException e) {
		}
        astAwareIncrementalBuild = CeylonBuilder.areAstAwareIncrementalBuildsEnabled(project);
    }

    @Override
    public boolean visit(IResourceDelta resourceDelta) 
            throws CoreException {
        IResource resource = resourceDelta.getResource();
        
        if (resource instanceof IProject) { 
            if ((resourceDelta.getFlags() & IResourceDelta.DESCRIPTION)!=0) {
                //some project setting changed : don't do anything, 
                // since the possibly impacting changes have already been
                // checked by JavaProjectStateManager.hasClasspathChanges()
            }
            else if (!resource.equals(project)) {
                //this is some kind of multi-project build,
                //indicating a change in a project we
                //depend upon
                /*mustDoFullBuild.value = true;
                mustResolveClasspathContainer.value = true;*/
            }
        }
        
        if (resource instanceof IFolder) {
            IFolder folder = (IFolder) resource; 
            if (resourceDelta.getKind()==IResourceDelta.REMOVED) {
                Package pkg = getPackage(folder);
                if (pkg!=null) {
                    //a package has been removed
                    mustDoFullBuild.value = true;
                } 
                
                IPath fullPath = resource.getFullPath();
                if (fullPath != null) {
            		if (explodedDirPath != null && explodedDirPath.isPrefixOf(fullPath)) {
                        mustDoFullBuild.value = true;
                        mustResolveClasspathContainer.value = true;
            		}

                	for (Map.Entry<IProject, IPath> entry : modulesDirPathByProject.entrySet()) {
                		IPath modulesDirPath = entry.getValue();
                		if (modulesDirPath != null && modulesDirPath.isPrefixOf(fullPath)) {
	                        mustDoFullBuild.value = true;
	                        mustResolveClasspathContainer.value = true;
                		}
                	}
                }
            } else {
                if (folder.exists() && folder.getProject().equals(project)) {
                    if (getPackage(folder) == null || getRootFolder(folder) == null) {
                        IContainer parent = folder.getParent();
                        if (parent instanceof IFolder) {
                            Package parentPkg = getPackage((IFolder)parent);
                            IFolder rootFolder = getRootFolder((IFolder)parent);
                            if (parentPkg != null && rootFolder != null) {
                                Package pkg = getProjectModelLoader(project).findOrCreatePackage(parentPkg.getModule(), parentPkg.getNameAsString() + "." + folder.getName());
                                resource.setSessionProperty(CeylonBuilder.RESOURCE_PROPERTY_PACKAGE_MODEL, new WeakReference<Package>(pkg));
                                resource.setSessionProperty(CeylonBuilder.RESOURCE_PROPERTY_ROOT_FOLDER, rootFolder);
                            }
                        }
                    }
                }
            }
            
        }
        
        if (resource instanceof IFile) {
            IFile file = (IFile) resource;
            String fileName = file.getName();
            if (isInSourceFolder(file)) {
                if (fileName.equals(ModuleManager.PACKAGE_FILE) || fileName.equals(ModuleManager.MODULE_FILE)) {
                    //a package or module descriptor has been added, removed, or changed
                    boolean descriptorContentChanged = true;
                    if (astAwareIncrementalBuild && file.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO) <= IMarker.SEVERITY_WARNING) {
                        IResourceAware unit = CeylonBuilder.getUnit(file);
                        if (unit instanceof ProjectSourceFile) {
                            ProjectSourceFile projectSourceFile = (ProjectSourceFile) unit;
                            CompilationUnitDelta delta = projectSourceFile.buildDeltaAgainstModel();
                            if (delta != null
                                    && delta.getChanges().getSize() == 0
                                    && delta.getChildrenDeltas().getSize() == 0) {
                                descriptorContentChanged = false;
                            }
                        }
                    }
                    if (descriptorContentChanged) {
                        mustDoFullBuild.value = true;<commit_msg>Exception when removing package descriptor<commit_after>package com.redhat.ceylon.eclipse.core.builder;

import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getPackage;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getProjectModelLoader;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.getRootFolder;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.isInSourceFolder;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.isResourceFile;
import static com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.isSourceFile;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;

import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleManager;
import com.redhat.ceylon.compiler.typechecker.model.Package;
import com.redhat.ceylon.eclipse.core.builder.CeylonBuilder.BooleanHolder;
import com.redhat.ceylon.eclipse.core.model.IResourceAware;
import com.redhat.ceylon.eclipse.core.model.ProjectSourceFile;
import com.redhat.ceylon.eclipse.ui.ceylon.model.delta.CompilationUnitDelta;

final class DeltaScanner implements IResourceDeltaVisitor {
    private final BooleanHolder mustDoFullBuild;
    private final IProject project;
    private final BooleanHolder somethingToBuild;
    private final BooleanHolder mustResolveClasspathContainer;
	private IPath explodedDirPath;
	private Map<IProject, IPath> modulesDirPathByProject = new HashMap<>();
	private boolean astAwareIncrementalBuild = true;
	
    DeltaScanner(BooleanHolder mustDoFullBuild, IProject project,
            BooleanHolder somethingToBuild,
            BooleanHolder mustResolveClasspathContainer) {
        this.mustDoFullBuild = mustDoFullBuild;
        this.project = project;
        this.somethingToBuild = somethingToBuild;
        this.mustResolveClasspathContainer = mustResolveClasspathContainer;
        IFolder explodedFolder = CeylonBuilder.getCeylonClassesOutputFolder(project);
        explodedDirPath = explodedFolder != null ? explodedFolder.getFullPath() : null;
        IFolder modulesFolder = CeylonBuilder.getCeylonModulesOutputFolder(project);
        IPath modulesDirPath = modulesFolder != null ? modulesFolder.getFullPath() : null;
        modulesDirPathByProject.put(project, modulesDirPath);
        try {
			for (IProject referencedProject : project.getReferencedProjects()) {
		        modulesFolder = CeylonBuilder.getCeylonModulesOutputFolder(referencedProject);
		        modulesDirPath = modulesFolder != null ? modulesFolder.getFullPath() : null;
		        modulesDirPathByProject.put(referencedProject, modulesDirPath);
			}
		} catch (CoreException e) {
		}
        astAwareIncrementalBuild = CeylonBuilder.areAstAwareIncrementalBuildsEnabled(project);
    }

    @Override
    public boolean visit(IResourceDelta resourceDelta) 
            throws CoreException {
        IResource resource = resourceDelta.getResource();
        
        if (resource instanceof IProject) { 
            if ((resourceDelta.getFlags() & IResourceDelta.DESCRIPTION)!=0) {
                //some project setting changed : don't do anything, 
                // since the possibly impacting changes have already been
                // checked by JavaProjectStateManager.hasClasspathChanges()
            }
            else if (!resource.equals(project)) {
                //this is some kind of multi-project build,
                //indicating a change in a project we
                //depend upon
                /*mustDoFullBuild.value = true;
                mustResolveClasspathContainer.value = true;*/
            }
        }
        
        if (resource instanceof IFolder) {
            IFolder folder = (IFolder) resource; 
            if (resourceDelta.getKind()==IResourceDelta.REMOVED) {
                Package pkg = getPackage(folder);
                if (pkg!=null) {
                    //a package has been removed
                    mustDoFullBuild.value = true;
                } 
                
                IPath fullPath = resource.getFullPath();
                if (fullPath != null) {
            		if (explodedDirPath != null && explodedDirPath.isPrefixOf(fullPath)) {
                        mustDoFullBuild.value = true;
                        mustResolveClasspathContainer.value = true;
            		}

                	for (Map.Entry<IProject, IPath> entry : modulesDirPathByProject.entrySet()) {
                		IPath modulesDirPath = entry.getValue();
                		if (modulesDirPath != null && modulesDirPath.isPrefixOf(fullPath)) {
	                        mustDoFullBuild.value = true;
	                        mustResolveClasspathContainer.value = true;
                		}
                	}
                }
            } else {
                if (folder.exists() && folder.getProject().equals(project)) {
                    if (getPackage(folder) == null || getRootFolder(folder) == null) {
                        IContainer parent = folder.getParent();
                        if (parent instanceof IFolder) {
                            Package parentPkg = getPackage((IFolder)parent);
                            IFolder rootFolder = getRootFolder((IFolder)parent);
                            if (parentPkg != null && rootFolder != null) {
                                Package pkg = getProjectModelLoader(project).findOrCreatePackage(parentPkg.getModule(), parentPkg.getNameAsString() + "." + folder.getName());
                                resource.setSessionProperty(CeylonBuilder.RESOURCE_PROPERTY_PACKAGE_MODEL, new WeakReference<Package>(pkg));
                                resource.setSessionProperty(CeylonBuilder.RESOURCE_PROPERTY_ROOT_FOLDER, rootFolder);
                            }
                        }
                    }
                }
            }
            
        }
        
        if (resource instanceof IFile) {
            IFile file = (IFile) resource;
            String fileName = file.getName();
            if (isInSourceFolder(file)) {
                if (fileName.equals(ModuleManager.PACKAGE_FILE) || fileName.equals(ModuleManager.MODULE_FILE)) {
                    //a package or module descriptor has been added, removed, or changed
                    boolean descriptorContentChanged = true;
                    if (astAwareIncrementalBuild && file.isAccessible() &&  file.findMaxProblemSeverity(IMarker.PROBLEM, true, IResource.DEPTH_ZERO) <= IMarker.SEVERITY_WARNING) {
                        IResourceAware unit = CeylonBuilder.getUnit(file);
                        if (unit instanceof ProjectSourceFile) {
                            ProjectSourceFile projectSourceFile = (ProjectSourceFile) unit;
                            CompilationUnitDelta delta = projectSourceFile.buildDeltaAgainstModel();
                            if (delta != null
                                    && delta.getChanges().getSize() == 0
                                    && delta.getChildrenDeltas().getSize() == 0) {
                                descriptorContentChanged = false;
                            }
                        }
                    }
                    if (descriptorContentChanged) {
                        mustDoFullBuild.value = true;
{'fraction_non_alphanumeric': 0.08232241323386312, 'fraction_numerical': 0.0003892312682452157, 'mean_word_length': 2.2016614745586707, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3321637', 'n_tokens_mistral': 3929, 'n_tokens_neox': 3751, 'n_words': 716}