Skip to content

Commit 6294205

Browse files
committed
#12 Add quick-fix to ignore "Unmapped target properties".
1 parent 43e2731 commit 6294205

File tree

9 files changed

+660
-1
lines changed

9 files changed

+660
-1
lines changed

org.mapstruct.eclipse.feature/feature.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<description>
2929
MapStruct tooling support:
3030
- Content Assist
31+
- Quick-Fixes
3132
</description>
3233

3334
<copyright>
@@ -49,6 +50,29 @@ See the License for the specific language governing permissions and
4950
limitations under the License.
5051
</copyright>
5152

53+
<license url="http://www.apache.org/licenses/LICENSE-2.0">
54+
Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
55+
and/or other contributors as indicated by the @authors tag. See the
56+
copyright.txt file in the distribution for a full listing of all
57+
contributors.
58+
59+
Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
60+
you may not use this file except in compliance with the License.
61+
You may obtain a copy of the License at
62+
63+
http://www.apache.org/licenses/LICENSE-2.0
64+
65+
Unless required by applicable law or agreed to in writing, software
66+
distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
67+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68+
See the License for the specific language governing permissions and
69+
limitations under the License.
70+
</license>
71+
72+
<url>
73+
<discovery label="MapStruct" url="http://www.mapstruct.org"/>
74+
</url>
75+
5276
<requires>
5377
<import plugin="org.eclipse.ui"/>
5478
<import plugin="org.eclipse.core.runtime"/>

org.mapstruct.eclipse/META-INF/MANIFEST.MF

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ Require-Bundle: org.eclipse.ui,
88
org.eclipse.core.runtime,
99
org.eclipse.jdt.core,
1010
org.eclipse.jdt.ui,
11-
org.eclipse.jface.text
11+
org.eclipse.jface.text,
12+
org.eclipse.ui.ide;bundle-version="3.10.0",
13+
org.eclipse.core.resources;bundle-version="3.9.0",
14+
org.eclipse.ui.editors;bundle-version="3.8.200"
1215
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
1316
Bundle-ActivationPolicy: lazy
1417
Bundle-Vendor: MapStruct.org

org.mapstruct.eclipse/plugin.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,12 @@
4747
needsSortingAfterFiltering="true">
4848
</javaCompletionProposalComputer>
4949
</extension>
50+
51+
<extension
52+
id="MapStructMarkerResolution"
53+
point="org.eclipse.ui.ide.markerResolution">
54+
<markerResolutionGenerator
55+
markerType="org.eclipse.jdt.apt.pluggable.core.compileProblem"
56+
class="org.mapstruct.eclipse.internal.quickfix.MapStructMarkerResolutionGenerator"/>
57+
</extension>
5058
</plugin>

org.mapstruct.eclipse/src/org/mapstruct/eclipse/internal/MapStructAPIConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,9 @@ private MapStructAPIConstants() {
6868
* Member name of Mapping#target()
6969
*/
7070
public static final String MAPPING_MEMBER_TARGET = "target"; //$NON-NLS-1$
71+
72+
/**
73+
* Member name of Mapping#ignore()
74+
*/
75+
public static final String MAPPING_MEMBER_IGNORE = "ignore"; //$NON-NLS-1$
7176
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.eclipse.internal.quickfix;
20+
21+
import java.util.ArrayList;
22+
import java.util.Arrays;
23+
import java.util.Collection;
24+
import java.util.List;
25+
26+
import org.eclipse.core.resources.IMarker;
27+
import org.eclipse.core.runtime.CoreException;
28+
import org.eclipse.ui.IMarkerResolution;
29+
import org.eclipse.ui.IMarkerResolutionGenerator;
30+
import org.mapstruct.eclipse.internal.quickfix.fixes.AddIgnoreTargetMappingAnnotationQuickFix;
31+
32+
/**
33+
* Creates possible marker resolutions, i.e. quick fixes for errors that read like being generated by MapStruct
34+
*
35+
* @author Andreas Gudian
36+
*/
37+
public class MapStructMarkerResolutionGenerator implements IMarkerResolutionGenerator {
38+
39+
private static final IMarkerResolution[] NO_RESOLUTIONS = new IMarkerResolution[0];
40+
41+
private Collection<? extends MapStructQuickFix> allFixes = allQuickFixes();
42+
43+
@Override
44+
public IMarkerResolution[] getResolutions(IMarker mk) {
45+
try {
46+
if ( isAptCompileProblem( mk ) ) {
47+
return findApplicableFixes( mk );
48+
}
49+
}
50+
catch ( CoreException e ) {
51+
return NO_RESOLUTIONS;
52+
}
53+
return NO_RESOLUTIONS;
54+
}
55+
56+
private static boolean isAptCompileProblem(IMarker mk) throws CoreException {
57+
return "org.eclipse.jdt.apt.pluggable.core.compileProblem".equals( mk.getType() );
58+
}
59+
60+
private IMarkerResolution[] findApplicableFixes(IMarker mk) throws CoreException {
61+
List<IMarkerResolution> result = new ArrayList<IMarkerResolution>();
62+
for ( MapStructQuickFix fix : allFixes ) {
63+
if ( fix.canFix( mk ) ) {
64+
result.add( fix );
65+
}
66+
}
67+
return result.toArray( new IMarkerResolution[result.size()] );
68+
}
69+
70+
private static Collection<? extends MapStructQuickFix> allQuickFixes() {
71+
return Arrays.asList(
72+
new AddIgnoreTargetMappingAnnotationQuickFix()
73+
);
74+
}
75+
}
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/**
2+
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
3+
* and/or other contributors as indicated by the @authors tag. See the
4+
* copyright.txt file in the distribution for a full listing of all
5+
* contributors.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.mapstruct.eclipse.internal.quickfix;
20+
21+
import java.util.Iterator;
22+
23+
import org.eclipse.core.resources.IMarker;
24+
import org.eclipse.core.resources.IResource;
25+
import org.eclipse.core.runtime.CoreException;
26+
import org.eclipse.jdt.core.ICompilationUnit;
27+
import org.eclipse.jdt.core.IJavaElement;
28+
import org.eclipse.jdt.core.JavaCore;
29+
import org.eclipse.jdt.core.dom.AST;
30+
import org.eclipse.jdt.core.dom.ASTNode;
31+
import org.eclipse.jdt.core.dom.CompilationUnit;
32+
import org.eclipse.jdt.core.dom.ImportDeclaration;
33+
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
34+
import org.eclipse.jdt.internal.ui.JavaPlugin;
35+
import org.eclipse.jdt.internal.ui.JavaPluginImages;
36+
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
37+
import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
38+
import org.eclipse.jdt.ui.SharedASTProvider;
39+
import org.eclipse.jface.text.Position;
40+
import org.eclipse.jface.text.source.Annotation;
41+
import org.eclipse.jface.text.source.IAnnotationModel;
42+
import org.eclipse.swt.graphics.Image;
43+
import org.eclipse.ui.IEditorInput;
44+
import org.eclipse.ui.IMarkerResolution2;
45+
import org.eclipse.ui.texteditor.MarkerAnnotation;
46+
import org.mapstruct.eclipse.internal.quickfix.visitors.FindMethodByPositionVisitor;
47+
48+
/**
49+
* Base class for quick fixes
50+
*
51+
* @author Andreas Gudian
52+
*/
53+
@SuppressWarnings("restriction")
54+
public abstract class MapStructQuickFix implements IMarkerResolution2 {
55+
private String label;
56+
57+
protected MapStructQuickFix(String label) {
58+
this.label = label;
59+
}
60+
61+
@Override
62+
public String getLabel() {
63+
return label;
64+
}
65+
66+
@Override
67+
public void run(IMarker marker) {
68+
ICompilationUnit compilationUnit = null;
69+
try {
70+
IResource resource = marker.getResource();
71+
IJavaElement javaElement = JavaCore.create( resource );
72+
73+
compilationUnit = (ICompilationUnit) javaElement.getAdapter( ICompilationUnit.class );
74+
IEditorInput input = EditorUtility.getEditorInput( compilationUnit );
75+
if ( input != null ) {
76+
CompilationUnit astCompilationUnit = toAST( compilationUnit );
77+
78+
ASTNode locatedNode =
79+
locateASTNodeForSartingOffset( findProblemStart( input, marker ), astCompilationUnit );
80+
if ( locatedNode != null ) {
81+
ASTRewrite rewrite = getASTRewrite( astCompilationUnit, locatedNode, marker );
82+
83+
if ( rewrite != null ) {
84+
compilationUnit.applyTextEdit( rewrite.rewriteAST(), null );
85+
compilationUnit.becomeWorkingCopy( null );
86+
compilationUnit.commitWorkingCopy( true, null );
87+
compilationUnit.discardWorkingCopy();
88+
marker.delete();
89+
}
90+
}
91+
}
92+
}
93+
catch ( CoreException e ) {
94+
throw new RuntimeException( e );
95+
}
96+
}
97+
98+
/**
99+
* @param input editor input
100+
* @param marker the marker
101+
* @return the offset of the problem, either as currently computed in an open (dirty) editor, or as originally
102+
* stated in the marker
103+
* @throws CoreException
104+
*/
105+
@SuppressWarnings("unchecked")
106+
private static int findProblemStart(IEditorInput input, IMarker marker) throws CoreException {
107+
IAnnotationModel model =
108+
JavaPlugin.getDefault().getCompilationUnitDocumentProvider().getAnnotationModel( input );
109+
if ( model != null ) {
110+
Iterator<Annotation> iter = model.getAnnotationIterator();
111+
112+
while ( iter.hasNext() ) {
113+
Annotation curr = iter.next();
114+
if ( curr instanceof MarkerAnnotation ) {
115+
MarkerAnnotation annot = (MarkerAnnotation) curr;
116+
if ( marker.equals( annot.getMarker() ) ) {
117+
Position pos = model.getPosition( annot );
118+
if ( pos != null ) {
119+
return pos.getOffset();
120+
}
121+
}
122+
}
123+
}
124+
}
125+
126+
Integer charStart = (Integer) marker.getAttribute( IMarker.CHAR_START );
127+
128+
return charStart != null ? charStart : -1;
129+
}
130+
131+
private ASTNode locateASTNodeForSartingOffset(int problemOffset, CompilationUnit astCompilationUnit)
132+
throws CoreException {
133+
FindMethodByPositionVisitor visitor = new FindMethodByPositionVisitor( problemOffset );
134+
astCompilationUnit.accept( visitor );
135+
return visitor.getLocatedNode();
136+
}
137+
138+
/**
139+
* @param unit the compilation unit
140+
* @param nodeWithMarker the ASTNode that is located at the start position of the marker
141+
* @param marker the marker
142+
* @return the rewrite to be performed, or <code>null</code> in case no changes are to be performed
143+
*/
144+
protected abstract ASTRewrite getASTRewrite(CompilationUnit unit, ASTNode nodeWithMarker, IMarker marker);
145+
146+
/**
147+
* Add an import statement for the fullyQualifiedName if it is not yet imported
148+
*
149+
* @param compilationUnit the compilation unit
150+
* @param rewrite the rewrite to modify
151+
* @param fullyQualifiedName the fully qualified name of the type to add an import for
152+
*/
153+
protected void addImportIfRequired(CompilationUnit compilationUnit, ASTRewrite rewrite, String fullyQualifiedName) {
154+
if ( !hasImport( compilationUnit, fullyQualifiedName ) ) {
155+
AST ast = compilationUnit.getAST();
156+
ImportDeclaration declaration = ast.newImportDeclaration();
157+
declaration.setName( ast.newName( fullyQualifiedName ) );
158+
159+
rewrite.getListRewrite( compilationUnit, CompilationUnit.IMPORTS_PROPERTY ).insertLast( declaration, null );
160+
}
161+
}
162+
163+
private static boolean hasImport(CompilationUnit compilationUnit, String fullyQualifiedName) {
164+
for ( Object obj : compilationUnit.imports() ) {
165+
ImportDeclaration importDec = (ImportDeclaration) obj;
166+
if ( importDec.getName().getFullyQualifiedName().equals( fullyQualifiedName ) ) {
167+
return true;
168+
}
169+
}
170+
return false;
171+
}
172+
173+
@Override
174+
public String getDescription() {
175+
return null;
176+
}
177+
178+
@Override
179+
public Image getImage() {
180+
return JavaPluginImages.get( JavaPluginImages.IMG_CORRECTION_CHANGE );
181+
}
182+
183+
public abstract boolean canFix(IMarker marker);
184+
185+
/**
186+
* @param marker the marker
187+
* @return the message of the marker, or an empty string in case the message cannot be retrieved
188+
*/
189+
protected static String getMessage(IMarker marker) {
190+
try {
191+
return (String) marker.getAttribute( IMarker.MESSAGE );
192+
}
193+
catch ( CoreException e ) {
194+
return "";
195+
}
196+
}
197+
198+
private static CompilationUnit toAST(ICompilationUnit unit) {
199+
CompilationUnit astRoot = SharedASTProvider.getAST( unit, SharedASTProvider.WAIT_YES, null );
200+
if ( astRoot == null ) {
201+
astRoot = ASTResolving.createQuickFixAST( unit, null );
202+
}
203+
return astRoot;
204+
}
205+
}

0 commit comments

Comments
 (0)