Search in sources :

Example 1 with WorkspaceChanges

use of org.eclipse.n4js.xtext.workspace.WorkspaceChanges in project n4js by eclipse.

the class XWorkspaceBuilder method doIncrementalWorkspaceUpdateAndBuild.

/**
 * Based on the raw, "reported changes" accumulated in {@link #newDirtyFiles} / {@link #newDeletedFiles}, do the
 * following:
 * <ol>
 * <li>perform an update of the workspace configuration, if necessary, which may lead to additional "discovered
 * changes" (e.g. resources in newly added source folders),
 * <li><em>move</em> the "reported changes" together with the "discovered changes" to {@link #dirtyFiles} /
 * {@link #deletedFiles} / {@link #affectedByDeletedProjects},
 * <li>then trigger an incremental build.
 * </ol>
 */
protected IResourceDescription.Event doIncrementalWorkspaceUpdateAndBuild(CancelIndicator cancelIndicator) {
    // in case many incremental build tasks pile up in the queue (e.g. while a non-cancelable initial build is
    // running), we don't want to repeatedly invoke IWorkspaceManager#update() in each of those tasks but only in
    // the last one; therefore, we here check for a cancellation:
    operationCanceledManager.checkCanceled(cancelIndicator);
    Set<URI> newDirtyFiles = new LinkedHashSet<>(this.newDirtyFiles);
    Set<URI> newDeletedFiles = new LinkedHashSet<>(this.newDeletedFiles);
    boolean newRefreshRequest = this.newRefreshRequest;
    this.newDirtyFiles.clear();
    this.newDeletedFiles.clear();
    this.newRefreshRequest = false;
    Stopwatch stopwatch = Stopwatch.createStarted();
    if (newRefreshRequest) {
        lspLogger.log("Refreshing ...");
    }
    UpdateResult updateResult = workspaceManager.update(newDirtyFiles, newDeletedFiles, newRefreshRequest);
    WorkspaceChanges changes = updateResult.changes;
    List<URI> actualDirtyFiles = UtilN4.concat(changes.getAddedURIs(), changes.getChangedURIs());
    List<URI> actualDeletedFiles = new ArrayList<>(changes.getRemovedURIs());
    if (newRefreshRequest) {
        // scan all source folders of all projects for source file additions, changes, and deletions
        // - including source files of added projects,
        // - including source files of added source folders of existing projects,
        // - including source files of removed source folders of existing projects,
        // - *not* including source files of removed projects.
        actualDirtyFiles = new ArrayList<>();
        actualDeletedFiles = new ArrayList<>();
        for (ProjectBuilder projectBuilder : workspaceManager.getProjectBuilders()) {
            ResourceChangeSet sourceFileChanges = projectBuilder.scanForSourceFileChanges();
            actualDirtyFiles.addAll(sourceFileChanges.getDirty());
            actualDeletedFiles.addAll(sourceFileChanges.getDeleted());
        }
    } else {
        // scan only the added source folders (including those of added projects) for source files
        actualDirtyFiles.addAll(scanAddedSourceFoldersForNewSourceFiles(changes, scanner));
        // collect URIs from removed source folders (*not* including those of removed projects)
        actualDeletedFiles.addAll(getURIsFromRemovedSourceFolders(changes));
    }
    queue(this.dirtyFiles, actualDeletedFiles, actualDirtyFiles);
    queue(this.deletedFiles, actualDirtyFiles, actualDeletedFiles);
    // take care of removed projects
    Set<ProjectConfigSnapshot> deletedProjects = new HashSet<>();
    for (ProjectConfigSnapshot prjConfig : changes.getRemovedProjects()) {
        deletedProjects.add(prjConfig);
    }
    for (ProjectConfigSnapshot prjConfig : Iterables.concat(changes.getAddedProjects(), changes.getChangedProjects())) {
        deletedProjects.remove(prjConfig);
    }
    for (ProjectConfigSnapshot delPrj : deletedProjects) {
        ImmutableSet<? extends ProjectConfigSnapshot> affected = updateResult.oldWorkspaceConfigSnapshot.getProjectsDependingOn(delPrj.getName());
        this.affectedByDeletedProjects.addAll(affected);
    }
    handleContentsOfRemovedProjects(updateResult.removedProjectsContents);
    if (newRefreshRequest) {
        lspLogger.log("... refresh done (" + stopwatch.toString() + "; " + "projects added/removed: " + changes.getAddedProjects().size() + "/" + changes.getRemovedProjects().size() + "; " + "files dirty/deleted: " + dirtyFiles.size() + "/" + deletedFiles.size() + ").");
    }
    for (String cyclicProject : updateResult.cyclicProjectChanges) {
        ProjectConfigSnapshot projectConfig = workspaceManager.getWorkspaceConfig().findProjectByID(cyclicProject);
        Collection<URI> projectDescriptionUris = projectConfig.getProjectDescriptionUris();
        dirtyFiles.addAll(projectDescriptionUris);
    }
    if (dirtyFiles.isEmpty() && deletedFiles.isEmpty() && affectedByDeletedProjects.isEmpty()) {
        return new ResourceDescriptionChangeEvent(Collections.emptyList());
    }
    return doIncrementalBuild(cancelIndicator);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Stopwatch(com.google.common.base.Stopwatch) ArrayList(java.util.ArrayList) ResourceChangeSet(org.eclipse.n4js.xtext.ide.server.ResourceChangeSet) URI(org.eclipse.emf.common.util.URI) ResourceDescriptionChangeEvent(org.eclipse.xtext.resource.impl.ResourceDescriptionChangeEvent) WorkspaceChanges(org.eclipse.n4js.xtext.workspace.WorkspaceChanges) ProjectConfigSnapshot(org.eclipse.n4js.xtext.workspace.ProjectConfigSnapshot) UpdateResult(org.eclipse.n4js.xtext.ide.server.build.XWorkspaceManager.UpdateResult) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 2 with WorkspaceChanges

use of org.eclipse.n4js.xtext.workspace.WorkspaceChanges in project n4js by eclipse.

the class N4JSProjectConfig method computeChanges.

/**
 * Given two project configuration snapshots representing the old and new state of the receiving project, this
 * method computes the corresponding workspace changes. If no changes occurred, an empty {@link WorkspaceChanges}
 * instance will be returned.
 */
public static WorkspaceChanges computeChanges(ProjectConfigSnapshot oldProjectConfig, ProjectConfigSnapshot newProjectConfig) {
    Set<? extends SourceFolderSnapshot> oldSourceFolders = oldProjectConfig.getSourceFolders();
    Set<? extends SourceFolderSnapshot> newSourceFolders = newProjectConfig.getSourceFolders();
    // detect added/removed source folders
    Map<URI, SourceFolderSnapshot> oldSFs = new HashMap<>();
    Map<URI, SourceFolderSnapshot> newSFs = new HashMap<>();
    for (SourceFolderSnapshot sourceFolder : oldSourceFolders) {
        oldSFs.put(sourceFolder.getPath(), sourceFolder);
    }
    for (SourceFolderSnapshot sourceFolder : newSourceFolders) {
        newSFs.put(sourceFolder.getPath(), sourceFolder);
    }
    List<SourceFolderSnapshot> addedSourceFolders = new ArrayList<>();
    List<SourceFolderSnapshot> removedSourceFolders = new ArrayList<>();
    for (URI sfUri : Iterables.concat(oldSFs.keySet(), newSFs.keySet())) {
        boolean isOld = oldSFs.containsKey(sfUri);
        boolean isNew = newSFs.containsKey(sfUri);
        if (isOld && isNew) {
        // unchanged
        } else if (isOld && !isNew) {
            removedSourceFolders.add(oldSFs.get(sfUri));
        } else if (!isOld && isNew) {
            addedSourceFolders.add(newSFs.get(sfUri));
        }
    }
    if (Objects.equals(oldProjectConfig.getName(), newProjectConfig.getName())) {
        // detect changes in project properties
        boolean propertiesChanged = !addedSourceFolders.isEmpty() || !removedSourceFolders.isEmpty() || !Objects.equals(oldProjectConfig, newProjectConfig);
        return new WorkspaceChanges(ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.copyOf(removedSourceFolders), ImmutableList.copyOf(addedSourceFolders), ImmutableList.of(), ImmutableList.of(), propertiesChanged ? ImmutableList.of(newProjectConfig) : ImmutableList.of());
    } else {
        return new WorkspaceChanges(ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.copyOf(removedSourceFolders), ImmutableList.copyOf(addedSourceFolders), ImmutableList.of(oldProjectConfig), ImmutableList.of(newProjectConfig), ImmutableList.of());
    }
}
Also used : WorkspaceChanges(org.eclipse.n4js.xtext.workspace.WorkspaceChanges) SourceFolderSnapshot(org.eclipse.n4js.xtext.workspace.SourceFolderSnapshot) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(org.eclipse.emf.common.util.URI) FileURI(org.eclipse.n4js.workspace.locations.FileURI)

Example 3 with WorkspaceChanges

use of org.eclipse.n4js.xtext.workspace.WorkspaceChanges in project n4js by eclipse.

the class N4JSWorkspaceConfig method update.

@Override
public WorkspaceChanges update(WorkspaceConfigSnapshot oldWorkspaceConfig, Set<URI> dirtyFiles, Set<URI> deletedFiles, boolean refresh) {
    WorkspaceChanges changes = refresh ? doCompleteUpdate(oldWorkspaceConfig) : doMinimalUpdate(oldWorkspaceConfig, dirtyFiles, deletedFiles);
    changes = recomputeSemanticDependenciesIfNecessary(oldWorkspaceConfig, changes);
    return changes;
}
Also used : WorkspaceChanges(org.eclipse.n4js.xtext.workspace.WorkspaceChanges)

Example 4 with WorkspaceChanges

use of org.eclipse.n4js.xtext.workspace.WorkspaceChanges in project n4js by eclipse.

the class N4JSWorkspaceConfig method detectAddedRemovedProjects.

private WorkspaceChanges detectAddedRemovedProjects(WorkspaceConfigSnapshot oldWorkspaceConfig, boolean alsoDetectChangedProjects) {
    // update all projects
    reloadAllProjectInformationFromDisk();
    // detect project additions, removals (and also changes, iff 'alsoDetectChangedProjects' is set)
    Map<URI, ProjectConfigSnapshot> oldProjectsMap = IterableExtensions.toMap(oldWorkspaceConfig.getProjects(), ProjectConfigSnapshot::getPath);
    Map<URI, N4JSProjectConfig> newProjectsMap = IterableExtensions.toMap(getProjects(), XIProjectConfig::getPath);
    WorkspaceChanges changes = new WorkspaceChanges();
    for (URI uri : Sets.union(oldProjectsMap.keySet(), newProjectsMap.keySet())) {
        boolean isOld = oldProjectsMap.containsKey(uri);
        boolean isNew = newProjectsMap.containsKey(uri);
        if (isOld && !isNew) {
            // deleted
            changes = changes.merge(WorkspaceChanges.createProjectRemoved(oldProjectsMap.get(uri)));
        } else if (!isOld && isNew) {
            // added
            ProjectConfigSnapshot newPC = configSnapshotFactory.createProjectConfigSnapshot(newProjectsMap.get(uri));
            changes = changes.merge(WorkspaceChanges.createProjectAdded(newPC));
        } else if (isOld && isNew) {
            // check name change
            String oldPackageName = ((N4JSProjectConfigSnapshot) oldProjectsMap.get(uri)).getPackageName();
            String newPackageName = newProjectsMap.get(uri).getPackageName();
            if (Objects.equals(oldPackageName, newPackageName)) {
                // no change
                if (alsoDetectChangedProjects) {
                    ProjectConfigSnapshot oldPC = oldProjectsMap.get(uri);
                    ProjectConfigSnapshot newPC = configSnapshotFactory.createProjectConfigSnapshot(newProjectsMap.get(uri));
                    changes = changes.merge(N4JSProjectConfig.computeChanges(oldPC, newPC));
                }
            } else {
                // names changed
                ProjectConfigSnapshot newPC = configSnapshotFactory.createProjectConfigSnapshot(newProjectsMap.get(uri));
                changes = changes.merge(WorkspaceChanges.createProjectAdded(newPC));
                changes = changes.merge(WorkspaceChanges.createProjectRemoved(oldProjectsMap.get(uri)));
            }
        }
    }
    return changes;
}
Also used : ProjectConfigSnapshot(org.eclipse.n4js.xtext.workspace.ProjectConfigSnapshot) WorkspaceChanges(org.eclipse.n4js.xtext.workspace.WorkspaceChanges) XIProjectConfig(org.eclipse.n4js.xtext.workspace.XIProjectConfig) URI(org.eclipse.emf.common.util.URI) FileURI(org.eclipse.n4js.workspace.locations.FileURI)

Example 5 with WorkspaceChanges

use of org.eclipse.n4js.xtext.workspace.WorkspaceChanges in project n4js by eclipse.

the class N4JSWorkspaceConfig method doMinimalUpdate.

/**
 * Based on the given dirty/deleted files, performs a workspace update with as few computations as possible.
 */
private WorkspaceChanges doMinimalUpdate(WorkspaceConfigSnapshot oldWorkspaceConfig, Set<URI> dirtyFiles, Set<URI> deletedFiles) {
    WorkspaceChanges changes = WorkspaceChanges.createUrisRemovedAndChanged(deletedFiles, dirtyFiles);
    boolean needToDetectAddedRemovedProjects = false;
    for (URI changedResource : Iterables.concat(dirtyFiles, deletedFiles)) {
        String lastSegment = changedResource.lastSegment();
        boolean isPackageJson = lastSegment != null && lastSegment.equals(N4JSGlobals.PACKAGE_JSON);
        if (!isPackageJson) {
            continue;
        }
        ProjectConfigSnapshot oldProject = oldWorkspaceConfig.findProjectContaining(changedResource);
        XIProjectConfig project = oldProject != null ? findProjectByName(oldProject.getName()) : null;
        if (oldProject != null && project != null) {
            // an existing project was modified (maybe removed)
            changes = changes.merge(((N4JSProjectConfig) project).update(oldWorkspaceConfig, changedResource, configSnapshotFactory));
            if (((N4JSProjectConfig) project).isWorkspaceProject()) {
                needToDetectAddedRemovedProjects = true;
            }
        } else {
            // a new project was created
            needToDetectAddedRemovedProjects = true;
        }
    }
    needToDetectAddedRemovedProjects |= isProjectDiscoveryRequired(changes, oldWorkspaceConfig);
    if (needToDetectAddedRemovedProjects) {
        changes = changes.merge(detectAddedRemovedProjects(oldWorkspaceConfig, false));
    }
    return changes;
}
Also used : WorkspaceChanges(org.eclipse.n4js.xtext.workspace.WorkspaceChanges) ProjectConfigSnapshot(org.eclipse.n4js.xtext.workspace.ProjectConfigSnapshot) XIProjectConfig(org.eclipse.n4js.xtext.workspace.XIProjectConfig) URI(org.eclipse.emf.common.util.URI) FileURI(org.eclipse.n4js.workspace.locations.FileURI)

Aggregations

WorkspaceChanges (org.eclipse.n4js.xtext.workspace.WorkspaceChanges)6 URI (org.eclipse.emf.common.util.URI)5 FileURI (org.eclipse.n4js.workspace.locations.FileURI)4 ProjectConfigSnapshot (org.eclipse.n4js.xtext.workspace.ProjectConfigSnapshot)4 ArrayList (java.util.ArrayList)3 XIProjectConfig (org.eclipse.n4js.xtext.workspace.XIProjectConfig)3 Stopwatch (com.google.common.base.Stopwatch)1 FluentIterable (com.google.common.collect.FluentIterable)1 HashMultimap (com.google.common.collect.HashMultimap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Iterables (com.google.common.collect.Iterables)1 Sets (com.google.common.collect.Sets)1 Path (java.nio.file.Path)1 Collections (java.util.Collections)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 Map (java.util.Map)1