> As you say, it was not possible to efficiently extend the build problem
> detection functionality to CDT and keep it *DT independent. However, I
> think that your above suggestion would not work, because Resource Change
> listeners are language independent. The only difference between these
> two listeners would be that detectBuildProblem would have to behave
> differently according to the *DT. For this reason, these listeners are
> identical. Eclipse documentation states that adding a
> ResourceChangeListener has no effect if an identical listener is already
> registered.
These are not identical. The "identical" in the IWorkspace (Workspace)
means that the instance of the class extending IResourceChangeListener
is pointing the same address (Same meaning of the Object.equals(Object)).
Thus, the instantiating the difference class in a different time and
adding them is not adding the same reference objects to the workspace.
So it should work.
> case IResourceChangeEvent.POST_BUILD:
> /* Instead of using a visit method to visit all the
> children that was affected from the change
> * it is more efficient to be interested in the resource
> children who were changed.
> */
> try {
> IResourceDelta[] deltas =
> event.getDelta().getAffectedChildren(IResourceDelta.CHANGED);
> IMarkerDelta[] markerdeltas = null;
> for (int i = 0; i <= deltas.length; i++) {
> if ((deltas[i].getResource()) instanceof IProject) {
> /* More specifically, what we are interested
> in are the problem markers associated with the project
> * The following structure ensures that both
> JDT and CDT compatibility. Depending on the project nature
> * the proper problem marker is searched for.
> For not wasting too much time here, utility method
> * findMarkerDeltas of IResourceDelta is used.
> */
> IProject project = (IProject)
> deltas[i].getResource();
> if(project.hasNature(JavaCore.NATURE_ID)){
> markerdeltas =
> event.findMarkerDeltas(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,false);
> detectBuildProblem(markerdeltas);
> }
> else if((CoreModel.hasCCNature(project)) ||
> (CoreModel.hasCNature(project))) {
> markerdeltas =
> event.findMarkerDeltas(ICModelMarker.C_MODEL_PROBLEM_MARKER,false);
> detectBuildProblem(markerdeltas);
> }
> }
> }
> } catch (CoreException e) {
> e.printStackTrace();
> }
Good try. First attempt we are try to do is to get the result what we
want!. However, it seems that this still might not be efficient way.
Do you have any reason why you use the following?
> IResourceDelta[] deltas =
> event.getDelta().getAffectedChildren(IResourceDelta.CHANGED);
Is this to find the resource delta which is the instance of "IProject"?
Usually, the affected resource delta children is a lot of including
projects, folders, and files. so if a lot of resources are changed by a
file change, your iteration is huge to just find the instance which is
the instance of IProject. I recommend you to use, visiter pattern to find
the IProject instance, which is usually found after the workspaceroot
visit. so that, you might need only several iteration to find a project.
> IProject project = (IProject)
> deltas[i].getResource();
> if(project.hasNature(JavaCore.NATURE_ID)){
> markerdeltas =
> event.findMarkerDeltas(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,false);
> detectBuildProblem(markerdeltas);
> }
> else if((CoreModel.hasCCNature(project)) ||
> (CoreModel.hasCNature(project))) {
> markerdeltas =
> event.findMarkerDeltas(ICModelMarker.C_MODEL_PROBLEM_MARKER,false);
> detectBuildProblem(markerdeltas);
> }
I am not sure to use if else here. Rather I prefer creating own listener
for each language because it is more simple if another languages come
out such as COBOL, FORTRAN, etc. If this is the case, developer just
create own listener class and add it to workspace.
Cheers,
Takuya
On Tue, 07 Sep 2004 16:48:59 -0500
Turker Keskinpala <[EMAIL PROTECTED]> wrote:
> Hi Takuya,
>
> Thanks for your comments. I was working on changing the resource change
> structure and I think I came up with a working solution. I will try to
> explain here as I go through your suggestion below:
>
> >>>markers = fileEditorInput.getFile().findMarkers(
> >>> IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true,
> >>>IResource.DEPTH_INFINITE);
> >>>
> >>>should be changed with
> >>>
> >>>markers = fileEditorInput.getFile().findMarkers(
> >>> ICModelMarker.C_MODEL_PROBLEM_MARKER, true,
> >>>IResource.DEPTH_INFINITE);
> >>>
> >>>
> >
> >This change seems only supporting C/C++ problem marker so that you still can
> >not support both C/C++ and Java.
> >
> You are correct here since this is not what I wanted to do. I was trying
> to make the point that it is easy to look for C problem markers but I
> did not focus on the fact that I was looking for these on the active
> file. Actually, my aim is to make the whole think file editor specific.
>
> >I guess you and we have to change the
> >resource chage structure in such a way that each langauge specific
> >resource change listener should be imeplemented apart from the main
> >resourche change adapter which has been already implemented in the
> >EclipseSensor. My propose is that:
> >
> >[Java]
> >
> >JavaResourceChangeAdapter implements IResourceChangeListener, IResourceDeltaVisitor
> >{
> > ...
> > public boolean visit(IResourceDelta delta) throws CoreException {
> > ...
> > detectJavaBuildProblem();
> > ...
> > }
> >}
> >
> >[C/C++]
> >
> >CResourceChangeAdapter implements IResourceChangeListener, IResourceDeltaVisitor {
> >
> > public boolean visit(IResourceDelta delta) throws CoreException {
> > ...
> > detectCBuildProblem();
> > ...
> > }
> >}
> >
> >After creating own language adapter, you can add them to
> >
> >workspace.addResourceChangeListener(new CResourceChangeAdapter());
> >
> >This would enable sensor to extend any language in the future which
> >would be supported in Eclipse.
> >
> >
> As you say, it was not possible to efficiently extend the build problem
> detection functionality to CDT and keep it *DT independent. However, I
> think that your above suggestion would not work, because Resource Change
> listeners are language independent. The only difference between these
> two listeners would be that detectBuildProblem would have to behave
> differently according to the *DT. For this reason, these listeners are
> identical. Eclipse documentation states that adding a
> ResourceChangeListener has no effect if an identical listener is already
> registered.
>
> Instead of separating the resource change handling according to the *DT,
> I focused on separating the handling of specific resource change event
> types. In this case, the event types that we are interested in are
> POST_CHANGE (mainly to record open/close project, save/open/close file
> actions) and POST_BUILD to be able to detect and record build problems.
> The first change I made is to add the ResourceChangeAdapter to listen to
> POST_BUILD events as well as POST_CHANGE events:
>
> workspace.addResourceChangeListener(
> new ResourceChangeAdapter(),
> IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.POST_BUILD);
>
> Following that change, in the new resource change structure, two actions
> will be selected depending on the event type. POST_CHANGE events will be
> handled in the visit() method as have been. However, this time, the
> visit() method will not check the problem markers and will not make a
> call to detectBuildProblems().
>
> For the POST_BUILD events I decided not to use the visit pattern, since
> I figured I can do what I want to do without visiting all the files in
> the project. The Eclipse documentation recommends using available
> utility methods and spending less time if this is at all possible. So,
> when the POST_BUILD event occurs, I get only the affectedChildren which
> will be a project of some nature, check the project's nature, and use
> the IResourceEvent.findMarkerDeltas(String type, boolean
> includesubTypes) with the proper marker type depending on the project
> nature. Finally, I call the new detectBuildProblem(IMarkerDelta) method
> to record the problems that were ADDED or CHANGED. Below is the
> resourceChanged() method of the ResourceChangeAdapter and the
> detectBuildProblem method:
>
> public void resourceChanged(IResourceChangeEvent event) {
> IResource resource = event.getResource();
> // Need to select the proper action depending on the resource
> change event type
> switch (event.getType()) {
> case IResourceChangeEvent.POST_BUILD:
> /* Instead of using a visit method to visit all the
> children that was affected from the change
> * it is more efficient to be interested in the resource
> children who were changed.
> */
> try {
> IResourceDelta[] deltas =
> event.getDelta().getAffectedChildren(IResourceDelta.CHANGED);
> IMarkerDelta[] markerdeltas = null;
> for (int i = 0; i <= deltas.length; i++) {
> if ((deltas[i].getResource()) instanceof IProject) {
> /* More specifically, what we are interested
> in are the problem markers associated with the project
> * The following structure ensures that both
> JDT and CDT compatibility. Depending on the project nature
> * the proper problem marker is searched for.
> For not wasting too much time here, utility method
> * findMarkerDeltas of IResourceDelta is used.
> */
> IProject project = (IProject)
> deltas[i].getResource();
> if(project.hasNature(JavaCore.NATURE_ID)){
> markerdeltas =
> event.findMarkerDeltas(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,false);
> detectBuildProblem(markerdeltas);
> }
> else if((CoreModel.hasCCNature(project)) ||
> (CoreModel.hasCNature(project))) {
> markerdeltas =
> event.findMarkerDeltas(ICModelMarker.C_MODEL_PROBLEM_MARKER,false);
> detectBuildProblem(markerdeltas);
> }
> }
> }
> } catch (CoreException e) {
> e.printStackTrace();
> }
> case IResourceChangeEvent.POST_CHANGE:
> try {
> event.getDelta().accept(this);
> } catch (CoreException e1) {
> e1.printStackTrace();
> }
> }
> --------------------------------------------------------------------------------------------------
> private void detectBuildProblem(IMarkerDelta[] markerdeltas) {
> if (markerdeltas != null) {
> for (int i = 0; i <= markerdeltas.length; i++) {
> if ((markerdeltas[i].getKind() == IResourceDelta.ADDED)
> || (markerdeltas[i].getKind() == IResourceDelta.CHANGED)) {
> String data =
> markerdeltas[i].getResource().getLocation().toString() + "#" + (String)
> markerdeltas[i].getAttribute("message");
> String[] args = {"add", "Build Error", data};
> this.eclipseSensorShell.doCommand("Activity",
> Arrays.asList(args));
> }
>
> }
> }
> }
> --------------------------------------------------------------------------------------------------
>
> I tested this structure with both JDT and CDT and it worked as I
> expected. There is no preference to set, there is no file to change. One
> may work on CDT or JDT (and switch back and forth) and do not worry
> about what hackyEclipse is collecting. Another advantage this structure
> brings, in my opinion, is that, we are not dealing with active editor
> and approaching the build problem detection from a higher level (from
> the project level). I will keep testing and playing with it to see if
> there are any problems that I could not foresee.
>
> How does that implementation look?
>
> Cheers,
> Turker
================================
Takuya Yamashita
E-mail: [EMAIL PROTECTED]
================================