Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: fce6b457d7bdde42f3163a4d853b3f3ef3756793 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*******************************************************************************
 * Copyright (c) 2015 Anton Tanasenko
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *      Anton Tanasenko - Refactor marker resolutions and quick fixes (Bug #484359)
 *******************************************************************************/

package org.eclipse.m2e.core.ui.internal.markers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension5;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.views.markers.WorkbenchMarkerResolution;


/**
 * A single superclass for marker resolutions that can also act as completion proposals in text editor (e.g. shown when
 * called on ctrl+1)
 * 
 * @author atanasenko
 */
public abstract class MavenProblemResolution extends WorkbenchMarkerResolution
    implements ICompletionProposal, ICompletionProposalExtension5 {

  protected final Logger LOG = LoggerFactory.getLogger(this.getClass());

  private final IMarker marker;

  protected MavenProblemResolution(IMarker marker) {
    this.marker = marker;
  }

  public IMarker getMarker() {
    return this.marker;
  }

  public int getOrder() {
    return Integer.MAX_VALUE;
  }

  /**
   * Run this resolution for specified markers
   */
  protected abstract void fix(IMarker[] markers, IDocument document, IProgressMonitor monitor);

  /**
   * Tells whether this resolution should only be present once in a list of resolutions for any number of supported
   * markers and will always try to resolve them all
   */
  public boolean isSingleton() {
    return false;
  }

  public abstract boolean canFix(IMarker marker) throws CoreException;

  public Point getSelection(IDocument document) {
    return null;
  }

  public final String getDisplayString() {
    return getLabel();
  }

  public String getDescription() {
    return getLabel();
  }

  public String getAdditionalProposalInfo() {
    Object o = getAdditionalProposalInfo(new NullProgressMonitor());
    return o == null ? null : o.toString();
  }

  public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
    return getDescription();
  }

  public IContextInformation getContextInformation() {
    return null;
  }

  public final void run(IMarker marker) {
    run(marker, null);
  }

  public final void apply(IDocument document) {
    run(marker, document);
  }

  public final void run(IMarker[] markers, IProgressMonitor monitor) {
    fix(markers, null, monitor);
  }

  private void run(IMarker marker, IDocument document) {
    IMarker[] handledMarkers;

    if(isSingleton()) {
      try {
        IMarker[] allMarkers = ResourcesPlugin.getWorkspace().getRoot().findMarkers(null, true,
            IResource.DEPTH_INFINITE);
        handledMarkers = findOtherMarkers(allMarkers, true);
      } catch(CoreException e) {
        // fall back to running with a single marker
        handledMarkers = new IMarker[] {marker};
      }
    } else {
      handledMarkers = new IMarker[] {marker};
    }

    fix(handledMarkers, document, new NullProgressMonitor());
  }

  private IMarker[] findOtherMarkers(IMarker[] markers, boolean includeSelf) {
    List<IMarker> result = new ArrayList<>();
    for(IMarker marker : markers) {
      if(marker == this.marker && !includeSelf) {
        continue;
      }
      try {
        if(canFix(marker)) {
          result.add(marker);
        }
      } catch(CoreException ex) {
        LOG.error(ex.getMessage(), ex);
      }
    }
    return result.toArray(new IMarker[result.size()]);
  }

  public final IMarker[] findOtherMarkers(IMarker[] markers) {
    return findOtherMarkers(markers, false);
  }

  public boolean includeResolution(List<? super IMarkerResolution> resolutions) {
    if(shouldBeAdded(resolutions)) {
      resolutions.add(this);
      return true;
    }
    return false;
  }

  public boolean includeProposal(List<? super ICompletionProposal> proposals) {
    if(shouldBeAdded(proposals)) {
      proposals.add(this);
      return true;
    }
    return false;
  }

  private boolean shouldBeAdded(List<?> list) {
    if(isSingleton()) {
      for(Object o : list) {
        if(o.getClass().equals(this.getClass()))
          return false;
      }
    }
    return true;
  }

  protected Set<IProject> getProjects(Stream<IMarker> markers) {
    return markers.map(m -> m.getResource().getProject()).collect(Collectors.toSet());
  }

  public static List<IMarkerResolution> getResolutions(IMarker marker) {
    IMarkerResolution[] resolutions = IDE.getMarkerHelpRegistry().getResolutions(marker);
    List<IMarkerResolution> sortedResolutions = Arrays.asList(resolutions);
    Collections.sort(sortedResolutions,
        Comparator.<IMarkerResolution, Integer> comparing(MavenProblemResolution::getOrder)
            .thenComparing(IMarkerResolution::getLabel));
    return sortedResolutions;
  }

  public static int getOrder(IMarkerResolution res) {
    if(res instanceof MavenProblemResolution) {
      MavenProblemResolution mr = (MavenProblemResolution) res;
      return mr.getOrder();
    }
    return Integer.MAX_VALUE;
  }

  public static boolean hasResolutions(IMarker marker) {
    return IDE.getMarkerHelpRegistry().hasResolutions(marker);
  }
}

Back to the top