-
Notifications
You must be signed in to change notification settings - Fork 417
Update project if needed #547
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
Conversation
9011e8c
to
7dfdb92
Compare
Although I agree using a hash-based comparison is more robust than the current timestamp check, the current PR has 2 major flaws:
|
Well this PR proves something's wrong with #545 tests, since they should have failed with those changes |
26db36f
to
e190b15
Compare
@fbricon could you, please, take a look at the changes. I tried to fix your 2nd remark |
@fbricon the build is fine for me locally. No test fails. Could you, please, restart the build in Jenkins and look at this pr again? |
test this please |
@@ -26,23 +35,47 @@ | |||
*/ | |||
public class MavenBuildSupport implements IBuildSupport { | |||
|
|||
private static Map<Path, String> pomDigests = new ConcurrentHashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We definitely need to serialize that map to disk, either after it changes (safer) or on workspace shutdown. Else subsequent server(JVM) starts will ignore previous hash check so it'll be a regression in behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fbricon ok, working on it. Is there a special place where eclipse.jdt.ls serializes objects to? Or maybe you can advise the path
e190b15
to
f2a8168
Compare
* - a project to update | ||
* @param force | ||
* - defines if the <code>project</code> must be updated despite of | ||
* no changes of pom.xml are made |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no changes in the build descriptor are made
@@ -220,7 +220,8 @@ public void fileChanged(String uriString, CHANGE_TYPE changeType) { | |||
FeatureStatus status = preferenceManager.getPreferences().getUpdateBuildConfigurationStatus(); | |||
switch (status) { | |||
case automatic: | |||
updateProject(resource.getProject()); | |||
// do not force the build, because it's not started by user and should be done only if pom.xml has changed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/pom.xml/build file/
@@ -315,7 +316,7 @@ public IProject createJavaProject(IProject project, IProgressMonitor monitor) th | |||
return project; | |||
} | |||
|
|||
public Job updateProject(IProject project) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we might as well keep the update(IProject project)
flavour, to avoid the need to change to the more verbose update(project, false)
version all over the place. Needs javadoc explaining the 2 signatures
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method is only called twice from production code, so I think keeping it as is makes sense.
configurationManager.updateProjectConfiguration(request, monitor); | ||
// maven update should not be forced here, because it's a new project, just imported into workspace and | ||
// will be run automatically, because pom.xml-s have just appeared | ||
new MavenBuildSupport(configurationManager).update(project, monitor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move MavenBuildSupport instantiation out of the loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not do projectsManage.getBuildSupport(project).update(project, monitor)? The assumption we have is that MavenBuildSupport is stateless, but I don't really like that.
String newDigestStr = Arrays.toString(digest); | ||
synchronized (pomDigests) { | ||
String prevDigest = pomDigests.put(path.toString(), newDigestStr); | ||
if (prevDigest == null || !prevDigest.equals(newDigestStr)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!newDigestStr.equals(prevDigest))
static { | ||
File workspaceFile = ResourcesPlugin.getWorkspace().getRoot().getRawLocation().makeAbsolute().toFile(); | ||
SERIALIZATION_FILE = new File(workspaceFile, POM_SERLIZATION_FILE_NAME); | ||
if (SERIALIZATION_FILE.exists()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isFile()?
synchronized (pomDigests) { | ||
String prevDigest = pomDigests.put(path.toString(), newDigestStr); | ||
if (prevDigest == null || !prevDigest.equals(newDigestStr)) { | ||
serializePomDigests(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we serialize on every change?
configurationManager.updateProjectConfiguration(request, monitor); | ||
// maven update should not be forced here, because it's a new project, just imported into workspace and | ||
// will be run automatically, because pom.xml-s have just appeared | ||
new MavenBuildSupport(configurationManager).update(project, monitor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not do projectsManage.getBuildSupport(project).update(project, monitor)? The assumption we have is that MavenBuildSupport is stateless, but I don't really like that.
@@ -26,23 +41,87 @@ | |||
*/ | |||
public class MavenBuildSupport implements IBuildSupport { | |||
|
|||
private static final String POM_SERLIZATION_FILE_NAME = ".pom-digests"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like the fact that we're using a static map here. I guess it comes from the fact that MavenBuildSupport is used as a stateless object. I'd rather change that and keep the map in the instance.
Also, we should use the workspace state location available to eclipse plugins instead of using the workspace root.
import org.osgi.util.tracker.ServiceTracker; | ||
|
||
public class JavaLanguageServerPlugin implements BundleActivator { | ||
public class JavaLanguageServerPlugin extends Plugin { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getStateLocation() is on plugin
@@ -102,6 +104,7 @@ protected IStatus run(IProgressMonitor monitor) { | |||
|
|||
public ProjectsManager(PreferenceManager preferenceManager) { | |||
this.preferenceManager = preferenceManager; | |||
this.mavenBuildSupport = new MavenBuildSupport(MavenPlugin.getProjectConfigurationManager()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1. I'd like to decouple ProjectsManager from underlying build supports eventually. I expect buildSupports() implementation to load IBuildSupport instances from extension points, and don't want to make any assumption about the statefulness of each IBuildSupport.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're creating a new instance every time you need one, you ARE making an assumption, namely that build support is stateless. Keeping the same instance allows the implementers to be stateless or not.
IMNSHO (;-)) this is much better than keeping the digests in a static map.
MavenUpdateRequest request = new MavenUpdateRequest(project, MavenPlugin.getMavenConfiguration().isOffline(), true); | ||
configurationManager.updateProjectConfiguration(request, monitor); | ||
} | ||
|
||
private boolean needsMavenUpdate(IProject project) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the more I think of it the less I like this implementation. This method should simply check if a project needs an update. Updating the digests map should be done once the update is effectively triggered
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the two are really equivalent here, no? If the the digest is changed and an update needed, the project WILL be updated. So while not pretty, I think the logic is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it works for now. Until needsMavenUpdate is called from somewhere else (even in the same class since it's private) and no update is performed, then things will go wrong.
calling needsMavenUpdate twice in a row should yield the same results, always. Else, please change the method name to indicate it does more than checking.
@@ -25,24 +39,84 @@ | |||
* | |||
*/ | |||
public class MavenBuildSupport implements IBuildSupport { | |||
private Map<String, String> pomDigests; | |||
|
|||
private static final String POM_SERLIZATION_FILE_NAME = ".pom-digests"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
POM_SERIALIZATION_FILE_NAME
try (ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream(f))) { | ||
outStream.writeObject(pomDigests); | ||
} catch (IOException e) { | ||
JavaLanguageServerPlugin.logException("Exception occured while serizalizion of pom digests", e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while serializing pom digests
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f))) { | ||
return (Map<String, String>) ois.readObject(); | ||
} catch (IOException | ClassNotFoundException e) { | ||
JavaLanguageServerPlugin.logException("Exception occured while deserizalizion of pom digests", e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while deserializing pom digests
Ok so one major problem with this approach is we only serialize poms when a file change is detected. We should fingerprint them before importing them too, else you'll import the project, save a pom.xml without changing it, it'll be detected as an actual change and update will run |
26d4698
to
acfbc4b
Compare
Signed-off-by: Dmitrii Bocharov <[email protected]>
Signed-off-by: Dmitrii Bocharov <[email protected]>
Signed-off-by: Dmitrii Bocharov <[email protected]>
Signed-off-by: Dmitrii Bocharov <[email protected]>
Signed-off-by: Dmitrii Bocharov <[email protected]>
Signed-off-by: Snjezana Peco <[email protected]>
Signed-off-by: Thomas Mäder <[email protected]>
Signed-off-by: Thomas Mäder <[email protected]>
Signed-off-by: Thomas Mäder <[email protected]>
Signed-off-by: Thomas Mäder <[email protected]>
Signed-off-by: Thomas Mäder <[email protected]>
Signed-off-by: Thomas Mäder <[email protected]>
acfbc4b
to
8444b87
Compare
* | ||
*/ | ||
public class DigestStore { | ||
private Map<String, String> pomDigests; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fileDigests
eventually we could use the same mechanism for Gradle. Since this class has no coupling to Maven, I'd prefer we treat it as file-type agnostic.
|
||
private static final String POM_SERIALIZATION_FILE_NAME = ".pom-digests"; | ||
|
||
public DigestStore(Plugin plugin) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need a plugin object. Storage location path should be enough
@@ -121,6 +123,7 @@ public void start(BundleContext bundleContext) throws BackingStoreException { | |||
JavaManipulation.setPreferenceNodeId(PLUGIN_ID); | |||
preferenceManager = new PreferenceManager(); | |||
initializeJDTOptions(); | |||
digestStore = new DigestStore(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new DigestStore(getStateLocation())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duh!
Signed-off-by: Thomas Mäder <[email protected]>
|
||
} | ||
|
||
private void serializePomDigests() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
serializeFileDigests
} | ||
|
||
@SuppressWarnings("unchecked") | ||
private Map<String, String> deserializePomDigests() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deserializeFileDigests
Signed-off-by: Thomas Mäder <[email protected]>
squash merged as 6c64df5 |
although https://github.com/eclipse/eclipse.jdt.ls/pull/545/files was already merged, while i was working on this solution, still want to offer checking if
pom.xml
was changed not by comparing time, but by comparing md5 digests. In my opinion, it's more reliable, than checking the modification time of the whole workspace.This PR is far not ideal, and will be updated, in case the idea is accepted.