org.netbeans.modules.java.hints.MissingHashCode Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.java.hints;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreePath;
import java.awt.EventQueue;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.swing.JEditorPane;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.ModificationResult;
import org.netbeans.api.java.source.Task;
import org.netbeans.api.java.source.TreePathHandle;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.modules.java.editor.codegen.EqualsHashCodeGenerator;
import org.netbeans.spi.java.hints.Hint;
import org.netbeans.spi.java.hints.TriggerTreeKind;
import org.netbeans.spi.java.hints.HintContext;
import org.netbeans.spi.editor.hints.ChangeInfo;
import org.netbeans.spi.editor.hints.ErrorDescription;
import org.netbeans.spi.editor.hints.Fix;
import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
import org.netbeans.spi.java.hints.Hint.Options;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
/**
*
* @author Jaroslav tulach
*/
@Hint(displayName = "#DN_org.netbeans.modules.java.hints.MissingHashCode", description = "#DESC_org.netbeans.modules.java.hints.MissingHashCode", id="org.netbeans.modules.java.hints.MissingHashCode", category="general", enabled=true, options=Options.QUERY, suppressWarnings="EqualsAndHashcode")
public class MissingHashCode {
@TriggerTreeKind(Kind.CLASS)
public static List run(HintContext ctx) {
CompilationInfo compilationInfo = ctx.getInfo();
TreePath treePath = ctx.getPath();
Element clazz = compilationInfo.getTrees().getElement(treePath);
if (clazz == null || !clazz.getKind().isClass()) {
return null;
}
ExecutableElement[] ret = EqualsHashCodeGenerator.overridesHashCodeAndEquals(compilationInfo, clazz, new EqualsHashCodeGenerator.Cancel() {
@Override public boolean isCanceled() {
return false;
}
});
ExecutableElement warningToElement = null;
String addHint = null;
if (ret[0] == null && ret[1] != null) {
addHint = "MSG_GenEquals"; // NOI18N
warningToElement = ret[1];
}
if (ret[1] == null && ret[0] != null) {
addHint = "MSG_GenHashCode"; // NOI18N
warningToElement = ret[0];
}
if (addHint != null) {
assert warningToElement != null;
TreePath warningTo = compilationInfo.getTrees().getPath(warningToElement);
if (warningTo == null || warningTo.getLeaf().getKind() != Kind.METHOD) {
//XXX: should not happen, log
return null;
}
List fixes = Collections.singletonList(new FixImpl(
addHint,
TreePathHandle.create(clazz, compilationInfo),
compilationInfo.getFileObject()
));
int[] span = compilationInfo.getTreeUtilities().findNameSpan((MethodTree) warningTo.getLeaf());
if (span != null) {
ErrorDescription ed = ErrorDescriptionFactory.forName(
ctx,
warningTo,
NbBundle.getMessage(MissingHashCode.class, addHint),
fixes.toArray(new Fix[0])
);
return Collections.singletonList(ed);
}
}
return null;
}
public String getId() {
return getClass().getName();
}
public String getDisplayName() {
return NbBundle.getMessage(MissingHashCode.class, "MSG_MissingHashCode");
}
public String getDescription() {
return NbBundle.getMessage(MissingHashCode.class, "HINT_MissingHashCode");
}
private static final class FixImpl implements Fix, Runnable, Task {
private TreePathHandle handle;
private FileObject file;
private String msg;
private boolean fieldFound;
public FixImpl(String type, TreePathHandle handle, FileObject file) {
this.handle = handle;
this.file = file;
this.msg = type;
}
public String getText() {
return NbBundle.getMessage(MissingHashCode.class, msg);
}
public ChangeInfo implement() throws IOException {
ModificationResult result = JavaSource.forFileObject(file).runModificationTask(this);
if (fieldFound) {
EventQueue.invokeLater(this);
} else {
result.commit();
}
return null;
}
public void run() {
try {
EditorCookie cook = DataObject.find(file).getLookup().lookup(EditorCookie.class);
JEditorPane[] arr = cook.getOpenedPanes();
if (arr == null) {
return;
}
EqualsHashCodeGenerator.invokeEqualsHashCode(handle, arr[0]);
} catch (DataObjectNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
}
public void run(WorkingCopy wc) throws Exception {
wc.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
for (Element elem : handle.resolveElement(wc).getEnclosedElements()) {
if (elem.getKind() == ElementKind.FIELD) {
if (!elem.getModifiers().contains(Modifier.STATIC)) {
fieldFound = true;
return;
}
}
}
EqualsHashCodeGenerator.generateEqualsAndHashCode(wc, handle.resolve(wc));
}
@Override
public String toString() {
return "Fix";
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy