Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add commands to add/remove/list the project's source path #859

Merged
merged 1 commit into from
Dec 17, 2018

Conversation

testforstephen
Copy link
Contributor

@testforstephen testforstephen commented Nov 20, 2018

Signed-off-by: Jinbo Wang [email protected]

This is for feature redhat-developer/vscode-java#619, marking a folder as source root is helpful for the standalone java file support and simple eclipse project. Currently i disabled the operation on maven/gradle project because the user could manage this kind of source path through pom.xml and build.gradle.

Below is the basic feature:

  • Add Folder to Java Source Path (context menu)
  • Remove Folder from Java Source Path (context menu)
  • List all Java source paths (command palette)

See the peer PR redhat-developer/vscode-java#724

return projects;
}

public static IProject createInvisibleProjectIfNotExist(IPath workspaceRoot) throws OperationCanceledException, CoreException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this partly depends on #843?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Share the same InvisibleProject concept for the workspace without project descriptor. But the code doesn't have dependency because this is just a common utility method.

for (IClasspathEntry entry : existingEntries) {
if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
if (entry.getPath().equals(sourcePath)) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should return false, as nothing was added

@@ -83,4 +95,180 @@ public static String getJavaSourceLevel(IProject project) {
public static IProject[] getAllProjects() {
return ResourcesPlugin.getWorkspace().getRoot().getProjects();
}

public static void addSourcePath(IPath sourcePath, IJavaProject project) throws CoreException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return boolean

project.setRawClasspath(newEntries, project.getOutputLocation(), null);
}

public static void removeSourcePath(IPath sourcePath, IJavaProject project) throws CoreException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return boolean. true if actually deleted, else false

@testforstephen
Copy link
Contributor Author

test this please

@fbricon
Copy link
Contributor

fbricon commented Nov 30, 2018

@tsmaeder @svor @tolusha before we merge that to jdt.ls, I'd like one of you guys to review it as it overlaps with some Che/jdt.ls functionality.

@fbricon
Copy link
Contributor

fbricon commented Nov 30, 2018

Adding the same source multiple times keeps sending the "Successfully added" message

@fbricon
Copy link
Contributor

fbricon commented Nov 30, 2018

  • create A,java file in source folder
  • create newfolder, add as source folder
  • create B.java file in new source folder
  • make A extend B
  • remove newfolder from source path

No compilation error is raised on A.java, until A.java is reopened. Compilation errors should appear as soon as the newsource folder has been removed

@fbricon fbricon added this to the Mid December 2018 milestone Nov 30, 2018
@testforstephen
Copy link
Contributor Author

Cannot reproduce the scenario above. After the step remove newfolder from source path, WorkspaceDiagnistoicsHandler is able to detect the resource change event, and republish a diagnostic on the A.java.

Can reproduce the scenario under redhat-developer/vscode-java#724 (comment)

  • add source folder
  • add new class in new source folder
  • generate a compilation error (missing type), new diagnostic is added
  • remove source folder
  • diagnostic is not purged

The fix is to clear the diagnostics for the resource not on the classpath.

@testforstephen
Copy link
Contributor Author

testforstephen commented Dec 6, 2018

@fbricon After merge with the upstream master branch, i can reproduce scenario above. Looks like the new change 8ee5455 will skip the diagnostics republish for the A.java for build path change event.

image

Comment the if (!cu.isWorkingCopy()) statement under public boolean visit(IResourceDelta delta) throws CoreException, the diagnostic status can be reported correctly with add/remove build path.

private static final String UNSUPPORTED_ON_MAVEN = "Unsupported operation. Please use pom.xml file to manage the source directories of maven project.";
private static final String UNSUPPORTED_ON_GRADLE = "Unsupported operation. Please use build.gradle file to manage the source directories of gradle project.";

public static CommandResult addToSourcePath(String sourceFolder) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the format of "sourceFolder"? Why is this not a URI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, URI is better. Fixed.

public static CommandResult addToSourcePath(String sourceFolder) {
IPath sourceFolderPath = ResourceUtils.filePathFromURI(Paths.get(sourceFolder).toUri().toString());
IProject targetProject = findBelongedProject(sourceFolderPath);
if (targetProject != null && (ProjectUtils.isMavenProject(targetProject.getProject()) || ProjectUtils.isGradleProject(targetProject.getProject()))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What we really want to know here: is this a simple Eclipse project? Can we add that method to ProjectUtils? If we ever decide to clean project support up (because importers are contributions, reall, no?) we can fix it in one place.

return path;
}

public static class CommandResult {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're using a generic name, why not must "Result"?

this.message = message;
}

CommandResult(boolean status, String message, Object data) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the result holds data of different types, we should have different result classes.

@@ -127,6 +128,12 @@ public boolean visit(IResourceDelta delta) throws CoreException {
// Check if it is a Java ...
if (JavaCore.isJavaLikeFileName(file.getName())) {
ICompilationUnit cu = (ICompilationUnit) JavaCore.create(file);
// Clear the diagnostics for the resource not on the classpath
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make more sense go listen for classpath changes on the java model and remove diagnostics when a folder is removed from the classpath?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsmaeder From the classpath change event, we only know which project and which folder is affected. It's hard to infer which java files need refresh its diagnostics info. Adding or removing a source folder from classpath, it may cause compilation errors for java files under other source folders to be outdated too.

Here i just leverage the auto-build mechanism to tell us the problematic java files, and republish its diagnostics, because adding/removing source path operation will trigger the auto-build job so that the WorkspaceDiagnosticsHandler has a chance to republish the diagnostics.

I'm interested in the idea "listen for classpath changes on the java model" you mentioned, but not sure how to implement that, do you have more info? Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can start from JavaCore#addElementChangedListener() to learn about Java model deltas.

Copy link
Contributor Author

@testforstephen testforstephen Dec 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsmaeder Thanks for the info. Have a try on JavaCore#addElementChangedListener().
Considering the scenario below:

create A,java file in source folder
create newfolder, add as source folder
create B.java file in new source folder
make A extend B
remove newfolder from source path

Below is the execution flow:

Invoke the API JavaProject.setRawClasspath() to update the project's classpath.
-> IElementChangedListener receives .classpath Resource Delta (Remove From Classpath Event).
-> AutoBuildJob is triggered automatically.
-> IElementChangedListener receives the changed model. (Include A.java).
-> WorkspaceDiagnosticsHandler (because it implements IResourceChangeListener) will also receive the changed resource. (Include A.java).

Both listeners do the same thing. Their handle logic are similar, adding a new listener will cause duplicated logic to handle the same work.

So i prefer to use WorkspaceDiagnosticsHandler to refresh diagnostics.

@testforstephen
Copy link
Contributor Author

@tsmaeder @fbricon is it ok with the implementation about diagnostics refresh?

@testforstephen
Copy link
Contributor Author

@fbricon is it possible to include this feature in Mid December release?

Copy link
Contributor

@fbricon fbricon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might find we need to iterate more over the design of this feature, but for now it does its job as advertised, AFAICS, so I'm ok to merge this as a provisional feature.

@testforstephen please squash and rebase your PR into 1 commit. Once this is done, @yaohaizh can merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants