Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.core.resources; singleton:=true
Bundle-Version: 3.24.100.qualifier
Bundle-Version: 3.25.100.qualifier

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Bump seem to be wrong

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

New API, hence the bump.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The bump shouldn't include service segment!

@merks merks Jul 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The point is that a bump of the minor version sets the service version back to zero so it should be 3.25.0 not 3.25.100

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think in the past we had the rule to use 100 in the end to allow downports. Is that obsolete? https://github.com/eclipse-platform/eclipse.platform/blob/master/docs/VersionNumbering.md#when-to-change-the-service-segment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Forget this comment, this is for the first change of the third segment. Not the other one, so 3.25.0 would be correct.

I leave this as it is for now as we anyhow want tracing and not new API.

Bundle-Activator: org.eclipse.core.resources.ResourcesPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IncrementalProjectBuilder;
Expand Down Expand Up @@ -262,6 +263,11 @@ private void basicBuild(int trigger, IncrementalProjectBuilder builder, Map<Stri
currentTree = ((trigger == IncrementalProjectBuilder.FULL_BUILD) || clean) ? null : workspace.getElementTree();
int depth = -1;
ISchedulingRule rule = null;
IProject builderProject = builder.getProject();
ICommand builderCommand = builder.getCommand();
String builderName = builderCommand != null ? builderCommand.getBuilderName() : null;
workspace.broadcastProjectBuildEvent(builderProject, builderName,
IResourceChangeEvent.PRE_PROJECT_BUILD, trigger);
try {
//short-circuit if none of the projects this builder cares about have changed.
if (!needsBuild(currentBuilder, trigger)) {
Expand All @@ -274,9 +280,9 @@ private void basicBuild(int trigger, IncrementalProjectBuilder builder, Map<Stri
String name = currentBuilder.getLabel();
String message;
if (name != null) {
message = NLS.bind(Messages.events_invoking_2, name, builder.getProject().getFullPath());
message = NLS.bind(Messages.events_invoking_2, name, builderProject.getFullPath());
} else {
message = NLS.bind(Messages.events_invoking_1, builder.getProject().getFullPath());
message = NLS.bind(Messages.events_invoking_1, builderProject.getFullPath());
}
monitor.subTask(message);
hookStartBuild(builder, trigger);
Expand All @@ -302,34 +308,44 @@ private void basicBuild(int trigger, IncrementalProjectBuilder builder, Map<Stri
//do the build
SafeRunner.run(getSafeRunnable(currentBuilder, trigger, args, status, monitor));
} finally {
// Re-acquire the WS lock, then release the scheduling rule
if (depth >= 0) {
getWorkManager().endUnprotected(depth);
}
if (rule != null) {
try {
Job.getJobManager().endRule(rule);
} catch (IllegalArgumentException e) {
throw handleRuleConflict(false, currentBuilder, e);
// Re-acquire the WS lock and release the rule so POST_PROJECT_BUILD
// sees the same locking state as PRE_PROJECT_BUILD did.
try {
if (depth >= 0) {
getWorkManager().endUnprotected(depth);
}
}
// Be sure to clean up after ourselves.
if (clean || currentBuilder.wasForgetStateRequested()) {
currentBuilder.setLastBuiltTree(null);
} else if (currentBuilder.wasRememberStateRequested()) {
// If remember last build state, and FULL_BUILD
// last tree must be set to => null for next build
if (trigger == IncrementalProjectBuilder.FULL_BUILD) {
currentBuilder.setLastBuiltTree(null);
if (rule != null) {
try {
Job.getJobManager().endRule(rule);
} catch (IllegalArgumentException e) {
throw handleRuleConflict(false, currentBuilder, e);
}
}
} finally {
// Guarantee the matching POST_PROJECT_BUILD even if the handoff above threw.
try {
workspace.broadcastProjectBuildEvent(builderProject, builderName,
IResourceChangeEvent.POST_PROJECT_BUILD, trigger);
} finally {
// Be sure to clean up after ourselves.
if (clean || currentBuilder.wasForgetStateRequested()) {
currentBuilder.setLastBuiltTree(null);
} else if (currentBuilder.wasRememberStateRequested()) {
// If remember last build state, and FULL_BUILD
// last tree must be set to => null for next build
if (trigger == IncrementalProjectBuilder.FULL_BUILD) {
currentBuilder.setLastBuiltTree(null);
}
// else don't modify the last built tree
} else {
// remember the current state as the last built state.
ElementTree lastTree = workspace.getElementTree();
lastTree.immutable();
currentBuilder.setLastBuiltTree(lastTree);
}
hookEndBuild(builder);
}
// else don't modify the last built tree
} else {
// remember the current state as the last built state.
ElementTree lastTree = workspace.getElementTree();
lastTree.immutable();
currentBuilder.setLastBuiltTree(lastTree);
}
hookEndBuild(builder);
}
} finally {
currentBuilders.remove(currentBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,20 @@ private void cleanUp(ElementTree lastState, int type) {
}
}

/**
* Dispatches a per-builder build event (PRE_PROJECT_BUILD / POST_PROJECT_BUILD).
* Unlike {@link #broadcastChanges}, this computes no resource delta and does not
* touch {@code lastPostBuildTree}; the events are pure timing/metadata signals
* nested inside the enclosing workspace build.
*/
public void broadcastProjectBuildEvent(IProject project, String builderName, int type, int buildKind) {
if (!listeners.hasListenerFor(type)) {
return;
}
ResourceChangeEvent event = new ResourceChangeEvent(project, type, buildKind, project, builderName);
notify(getListeners(), event, false);
}

/**
* Helper method for the save participant lifecycle computation. */
public void broadcastChanges(IResourceChangeListener listener, int type, IResourceDelta delta) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* IBM Corporation - initial API and implementation
* James Blackburn (Broadcom Corp.) - ongoing development
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 473427
* Vogella GmbH - per-builder build events
*******************************************************************************/
package org.eclipse.core.internal.events;

Expand All @@ -32,6 +33,11 @@ public class ResourceChangeEvent extends EventObject implements IResourceChangeE
private int trigger = 0;
int type;

/**
* The builder id for PRE_PROJECT_BUILD / POST_PROJECT_BUILD events, or null.
*/
private String builderName;

protected ResourceChangeEvent(Object source, int type, IResource resource) {
super(source);
this.resource = resource;
Expand All @@ -45,6 +51,12 @@ public ResourceChangeEvent(Object source, int type, int buildKind, IResourceDelt
this.type = type;
}

public ResourceChangeEvent(Object source, int type, int buildKind, IResource resource, String builderName) {
this(source, type, resource);
this.trigger = buildKind;
this.builderName = builderName;
}

/**
* @see IResourceChangeEvent#findMarkerDeltas(String, boolean)
*/
Expand Down Expand Up @@ -107,6 +119,14 @@ public int getType() {
return type;
}

/**
* @see IResourceChangeEvent#getBuilderName()
*/
@Override
public String getBuilderName() {
return builderName;
}

public void setDelta(IResourceDelta value) {
delta = value;
}
Expand All @@ -133,6 +153,12 @@ public String toDebugString() {
case PRE_REFRESH :
output.append("PRE_REFRESH"); //$NON-NLS-1$
break;
case PRE_PROJECT_BUILD :
output.append("PRE_PROJECT_BUILD"); //$NON-NLS-1$
break;
case POST_PROJECT_BUILD :
output.append("POST_PROJECT_BUILD"); //$NON-NLS-1$
break;
default :
output.append("?"); //$NON-NLS-1$
break;
Expand All @@ -154,6 +180,9 @@ public String toDebugString() {
break;
}
output.append("\nResource: " + (resource == null ? "null" : resource)); //$NON-NLS-1$ //$NON-NLS-2$
if (builderName != null) {
output.append("\nBuilder: " + builderName); //$NON-NLS-1$
}
output.append("\nDelta:" + (delta == null ? " null" : ((ResourceDelta) delta).toDeepDebugString())); //$NON-NLS-1$ //$NON-NLS-2$
return output.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public String toString() {
private volatile int count8 = 0;
private volatile int count16 = 0;
private volatile int count32 = 0;
private volatile int count64 = 0;
private volatile int count128 = 0;

/**
* The list of listeners.
Expand Down Expand Up @@ -114,6 +116,12 @@ private void adding(int mask) {
if ((mask & 32) != 0) {
count32++;
}
if ((mask & 64) != 0) {
count64++;
}
if ((mask & 128) != 0) {
count128++;
}
}

/**
Expand All @@ -138,6 +146,10 @@ public boolean hasListenerFor(int event) {
return count16 > 0;
case 32:
return count32 > 0;
case 64:
return count64 > 0;
case 128:
return count128 > 0;
default:
return false;
}
Expand Down Expand Up @@ -170,6 +182,8 @@ public synchronized void clear() {
count8 = 0;
count16 = 0;
count32 = 0;
count64 = 0;
count128 = 0;
}

private void removing(int mask) {
Expand All @@ -191,6 +205,12 @@ private void removing(int mask) {
if ((mask & 32) != 0) {
count32--;
}
if ((mask & 64) != 0) {
count64--;
}
if ((mask & 128) != 0) {
count128--;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,15 @@ public void broadcastBuildEvent(Object source, int type, int buildTrigger) {
notificationManager.broadcastChanges(tree, event, false);
}

/**
* Broadcasts a per-builder build event. The {@code type} must be either
* {@link IResourceChangeEvent#PRE_PROJECT_BUILD} or
* {@link IResourceChangeEvent#POST_PROJECT_BUILD}.
*/
public void broadcastProjectBuildEvent(IProject project, String builderName, int type, int buildTrigger) {
notificationManager.broadcastProjectBuildEvent(project, builderName, type, buildTrigger);
}

/**
* Broadcasts an internal workspace lifecycle event to interested
* internal listeners.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2014 IBM Corporation and others.
* Copyright (c) 2000, 2026 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -10,6 +10,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
* Vogella GmbH - per-builder build events
*******************************************************************************/
package org.eclipse.core.resources;

Expand Down Expand Up @@ -86,6 +87,20 @@
* method returns the project being refreshed.
* The workspace is closed for changes during notification of these events.
* </li>
* <li>
* Before-the-fact report that a single builder is about to run on a single
* project. Event type is <code>PRE_PROJECT_BUILD</code>; <code>getSource</code>
* returns the {@link IProject}, <code>getBuilderName</code> the builder id,
* and <code>getBuildKind</code> the kind of build. Fired once per builder,
* nested inside the enclosing <code>PRE_BUILD</code>/<code>POST_BUILD</code>
* pair, with no resource delta.
* </li>
* <li>
* After-the-fact report that a single builder has run on a single project.
* Event type is <code>POST_PROJECT_BUILD</code>; the accessors behave as for
* <code>PRE_PROJECT_BUILD</code>. Under parallel builds, events for different
* projects may be delivered concurrently on different threads.
* </li>
* </ul>
* <p>
* In order to handle additional event types that may be introduced
Expand Down Expand Up @@ -179,6 +194,26 @@ public interface IResourceChangeEvent {
*/
int PRE_REFRESH = 32;

/**
* Event type constant (bit mask) indicating that a single builder is about to
* run on a single project. <code>getSource</code> returns the {@link IProject},
* <code>getBuilderName</code> the builder id, and <code>getBuildKind</code> the
* kind of build; no resource delta is provided.
*
* @see #getBuilderName()
* @since 3.25
*/
int PRE_PROJECT_BUILD = 64;

/**
* Event type constant (bit mask) indicating that a single builder has run on a
* single project. Accessors behave as for {@link #PRE_PROJECT_BUILD}.
*
* @see #getBuilderName()
* @since 3.25
*/
int POST_PROJECT_BUILD = 128;

/**
* Returns all marker deltas of the specified type that are associated
* with resource deltas for this event. If <code>includeSubtypes</code>
Expand Down Expand Up @@ -262,6 +297,19 @@ public interface IResourceChangeEvent {
* @see #PRE_CLOSE
* @see #PRE_DELETE
* @see #PRE_REFRESH
* @see #PRE_PROJECT_BUILD
* @see #POST_PROJECT_BUILD
*/
int getType();

/**
* Returns the id of the builder this event relates to (as declared in the
* project's build spec) for {@link #PRE_PROJECT_BUILD} and
* {@link #POST_PROJECT_BUILD} events, or <code>null</code> for other events.
*
* @since 3.25
*/
default String getBuilderName() {
return null;
}
}
Loading
Loading