Skip to content

Commit

Permalink
file scanner ignores nested projects
Browse files Browse the repository at this point in the history
  • Loading branch information
mmews committed Jan 5, 2024
1 parent 0a6c520 commit 75e4630
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

import org.eclipse.emf.common.util.URI;
import org.eclipse.n4js.packagejson.projectDescription.ProjectDependency;
import org.eclipse.n4js.workspace.IN4JSSourceFolder;
import org.eclipse.n4js.workspace.N4JSProjectConfig;
import org.eclipse.n4js.workspace.N4JSProjectConfigSnapshot;
import org.eclipse.n4js.workspace.N4JSSourceFolder;
import org.eclipse.n4js.workspace.N4JSSourceFolderForPackageJson;
import org.eclipse.n4js.workspace.N4JSSourceFolderSnapshot;
import org.eclipse.n4js.workspace.N4JSSourceFolderSnapshotForPackageJson;
Expand Down Expand Up @@ -65,8 +65,8 @@ public N4JSSourceFolderSnapshot createSourceFolderSnapshot(ISourceFolder sourceF
if (sourceFolder instanceof N4JSSourceFolderForPackageJson) {
return new N4JSSourceFolderSnapshotForPackageJson((N4JSSourceFolderForPackageJson) sourceFolder);
}
IN4JSSourceFolder sourceFolderCasted = (IN4JSSourceFolder) sourceFolder;
N4JSSourceFolder sourceFolderCasted = (N4JSSourceFolder) sourceFolder;
return new N4JSSourceFolderSnapshot(sourceFolder.getName(), sourceFolder.getPath(),
sourceFolderCasted.getType(), sourceFolderCasted.getRelativePath());
sourceFolderCasted.getType(), sourceFolderCasted.getRelativePath(), sourceFolderCasted.getWorkspaces());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Copyright (c) 2024 NumberFour AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* NumberFour AG - Initial API and implementation
*/
package org.eclipse.n4js.workspace;

import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.common.util.URI;
import org.eclipse.n4js.N4JSGlobals;
import org.eclipse.n4js.utils.URIUtils;
import org.eclipse.n4js.workspace.utils.FileSystemScanner.IFileSystemScannerAcceptor;

/**
* File acceptor that skips nested workspace projects.
*/
public class FileSystemScannerAceptor implements IFileSystemScannerAcceptor<URI> {
private final List<PathMatcher> pathMatchers;
private List<URI> sources = new ArrayList<>();

/**
* Constructor
*/
@SuppressWarnings("resource")
public FileSystemScannerAceptor(URI uri, List<String> workspaces) {
super();
this.pathMatchers = new ArrayList<>();
Path root = Path.of(uri.toFileString());
if (workspaces != null) {
for (String glob : workspaces) {
pathMatchers.add(FileSystems.getDefault().getPathMatcher("glob:" + root.resolve(glob)));
}
}
}

@Override
public void accept(URI uri) {
if (sources != null && N4JSGlobals.ALL_N4_FILE_EXTENSIONS.contains(URIUtils.fileExtension(uri))) {
sources.add(uri);
}
}

@Override
public FileVisitResult acceptFile(URI uri) {
accept(uri);
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult acceptDirectory(URI uri) {
for (PathMatcher pathMatcher : pathMatchers) {
if (pathMatcher.matches(Path.of(uri.toFileString()))) {
return FileVisitResult.SKIP_SUBTREE;
}
}
return FileVisitResult.CONTINUE;
}

/** Returns the sources and resets the internal sources list. */
public List<URI> getSources() {
try {
return sources;
} finally {
this.sources = new ArrayList<>();
}
}

/** */
public List<PathMatcher> getPathMatchers() {
return pathMatchers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
*/
package org.eclipse.n4js.workspace;

import java.util.ArrayList;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.List;
import java.util.Objects;

Expand All @@ -24,11 +25,12 @@
* Wrapper around {@link SourceContainerDescription}.
*/
public class N4JSSourceFolder implements IN4JSSourceFolder {

private final N4JSProjectConfig project;
private final SourceContainerType type;
private final String relativePath;
private final FileURI absolutePath;
private final List<String> workspaces;
private final FileSystemScannerAceptor fssAcceptor;

/**
* Constructor
Expand All @@ -38,6 +40,8 @@ public N4JSSourceFolder(N4JSProjectConfig project, SourceContainerType type, Str
this.type = Objects.requireNonNull(type);
this.relativePath = Objects.requireNonNull(relativePath);
this.absolutePath = project.getAbsolutePath(relativePath);
this.workspaces = project.getProjectDescription().getWorkspaces();
this.fssAcceptor = new FileSystemScannerAceptor(getPath(), workspaces);
}

@Override
Expand Down Expand Up @@ -70,11 +74,30 @@ public FileURI getPathAsFileURI() {
return absolutePath;
}

/** */
public List<String> getWorkspaces() {
return workspaces;
}

@Override
public List<URI> getAllResources(IFileSystemScanner scanner) {
List<URI> sources = new ArrayList<>();
scanner.scan(getPath(), sources::add);
return sources;
scanner.scan(getPath(), fssAcceptor); // assumes a FileSystemScanner
return fssAcceptor.getSources();
}

@SuppressWarnings("restriction")
@Override
public boolean contains(URI uri) {
if (!IN4JSSourceFolder.super.contains(uri)) {
return false;
}
for (PathMatcher pathMatcher : fssAcceptor.getPathMatchers()) {
if (pathMatcher.matches(Path.of(uri.toFileString()))) {
return false;
}
}

return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
*/
package org.eclipse.n4js.workspace;

import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.List;
import java.util.Objects;

import org.eclipse.emf.common.util.URI;
import org.eclipse.n4js.packagejson.projectDescription.SourceContainerType;
import org.eclipse.n4js.workspace.locations.FileURI;
import org.eclipse.n4js.xtext.workspace.SourceFolderSnapshot;
import org.eclipse.xtext.util.IFileSystemScanner;
import org.eclipse.xtext.util.UriExtensions;

/**
Expand All @@ -25,12 +29,16 @@ public class N4JSSourceFolderSnapshot extends SourceFolderSnapshot {

private final SourceContainerType type;
private final String relativeLocation;
private final FileSystemScannerAceptor fssAcceptor;

/** Creates a new {@link N4JSSourceFolderSnapshot}. */
public N4JSSourceFolderSnapshot(String name, URI path, SourceContainerType type, String relativeLocation) {
public N4JSSourceFolderSnapshot(String name, URI path, SourceContainerType type, String relativeLocation,
List<String> workspaces) {

super(name, path);
this.type = type;
this.relativeLocation = relativeLocation;
this.fssAcceptor = new FileSystemScannerAceptor(path, workspaces);
}

/** The {@link SourceContainerType type}. */
Expand Down Expand Up @@ -67,6 +75,25 @@ public String toString() {
+ ", path: " + getPath() + " }";
}

@Override
public List<URI> getAllResources(IFileSystemScanner scanner) {
scanner.scan(getPath(), fssAcceptor);
return fssAcceptor.getSources();
}

@Override
public boolean contains(URI uri) {
if (!super.contains(uri)) {
return false;
}
for (PathMatcher pathMatcher : fssAcceptor.getPathMatchers()) {
if (pathMatcher.matches(Path.of(uri.toFileString()))) {
return false;
}
}

return true;
}
// ==============================================================================================================
// Convenience and utility methods (do not introduce additional data)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class N4JSSourceFolderSnapshotForPackageJson extends N4JSSourceFolderSnap
/** Creates a new {@link N4JSSourceFolderSnapshotForPackageJson}. */
public N4JSSourceFolderSnapshotForPackageJson(N4JSSourceFolderForPackageJson sourceFolder) {
super(sourceFolder.getName(), sourceFolder.getPath(), sourceFolder.getType(),
sourceFolder.getRelativePath());
sourceFolder.getRelativePath(), null);
this.packageJsonURI = sourceFolder.getPackageJsonURI();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
import org.eclipse.xtext.xbase.lib.IterableExtensions;

import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Sets;

/**
Expand All @@ -70,7 +70,8 @@ public class N4JSWorkspaceConfig implements XIWorkspaceConfig {
/** All projects registered in this workspace by their id. */
protected final Map<String, N4JSProjectConfig> projectID2ProjectConfig = new LinkedHashMap<>();
/** All projects by their package name. */
protected final HashMultimap<String, N4JSProjectConfig> packageName2ProjectConfigs = HashMultimap.create();
protected final LinkedHashMultimap<String, N4JSProjectConfig> packageName2ProjectConfigs = LinkedHashMultimap
.create();
/** Map between definition projects and their defined projects. */
protected final DefinitionProjectMap definitionProjects = new DefinitionProjectMap();
/** Set of all runtime-library project ids in the workspace. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,29 @@
import com.google.inject.Singleton;

/**
* A file system scanner that is aware of {@link FileVisitingAcceptor} to cut the traversal short.
* A file system scanner that is aware of {@link IFileSystemScannerAcceptor} to cut the traversal short.
*
* Compared to the default, it relies internally on {@link Files#walkFileTree(Path, java.nio.file.FileVisitor)} rather
* than manual traversal based on the {@link File file API}.
*/
@Singleton
public class FileSystemScanner implements IFileSystemScanner {

/** An {@link IAcceptor} that supports skipping subtrees when walking the file tree. */
public interface IFileSystemScannerAcceptor<T> extends IAcceptor<T> {
/** Callback on every visited directory */
default FileVisitResult acceptDirectory(T t) {
accept(t);
return FileVisitResult.CONTINUE;
}

/** Callback on every visited file */
default FileVisitResult acceptFile(T t) {
accept(t);
return FileVisitResult.CONTINUE;
}
}

@Override
public void scan(URI root, IAcceptor<URI> acceptor) {
File rootFile = URIUtils.toFile(root);
Expand All @@ -56,24 +71,36 @@ public void scan(URI root, IAcceptor<URI> acceptor) {
}

static class N4JSFileVisitor implements FileVisitor<Path> {
final IFileSystemScannerAcceptor<URI> fssAcceptor;
final IAcceptor<URI> acceptor;

N4JSFileVisitor(IAcceptor<URI> acceptor) {
this.acceptor = acceptor;
this.fssAcceptor = (acceptor instanceof IFileSystemScannerAcceptor)
? (IFileSystemScannerAcceptor<URI>) acceptor
: null;
}

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (dir.endsWith(N4JSGlobals.NODE_MODULES)) {
return FileVisitResult.SKIP_SUBTREE;
}
if (fssAcceptor != null) {
return fssAcceptor.acceptDirectory(new FileURI(dir.toFile()).toURI());
}
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
acceptor.accept(new FileURI(file.toFile()).toURI());
return FileVisitResult.CONTINUE;
URI uri = new FileURI(file.toFile()).toURI();
if (fssAcceptor != null) {
return fssAcceptor.acceptFile(uri);
} else {
acceptor.accept(uri);
return FileVisitResult.CONTINUE;
}
}

@Override
Expand All @@ -83,8 +110,9 @@ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOExce

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
if (exc != null)
if (exc != null) {
throw exc;
}
return FileVisitResult.CONTINUE;
}
}
Expand Down
Loading

0 comments on commit 75e4630

Please sign in to comment.