org.netbeans.modules.java.hints.StaticAccess 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.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreePath;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.ElementHandle;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.modules.java.hints.errors.Utilities;
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;
import org.netbeans.spi.java.hints.HintContext;
import org.netbeans.spi.java.hints.JavaFix;
import org.netbeans.spi.java.hints.TriggerTreeKind;
import org.openide.util.NbBundle;
/**
*
* @author Jaroslav tulach
*/
@Hint(displayName="#MSG_StaticAccessName", description="#HINT_StaticAccess", category="general", id="org.netbeans.modules.java.hints.StaticAccess", suppressWarnings={StaticAccess.SUPPRESS_WARNINGS_KEY, "", "AccessStaticViaInstance"})
public class StaticAccess {
static final String SUPPRESS_WARNINGS_KEY = "static-access";
protected static Fix computeFixes(CompilationInfo info, TreePath treePath, int[] bounds, int[] kind, String[] simpleName) {
if (treePath.getLeaf().getKind() != Kind.MEMBER_SELECT) {
return null;
}
MemberSelectTree mst = (MemberSelectTree)treePath.getLeaf();
Tree expression = mst.getExpression();
TreePath expr = new TreePath(treePath, expression);
TypeMirror tm = info.getTrees().getTypeMirror(expr);
if (!Utilities.isValidType(tm)) {
return null;
}
Element el = info.getTypes().asElement(tm);
if (el == null || (!el.getKind().isClass() && !el.getKind().isInterface())) {
return null;
}
TypeElement type = (TypeElement)el;
if (isError(type)) {
return null;
}
Name idName = null;
if (expression.getKind() == Kind.MEMBER_SELECT) {
MemberSelectTree exprSelect = (MemberSelectTree)expression;
idName = exprSelect.getIdentifier();
}
if (expression.getKind() == Kind.IDENTIFIER) {
IdentifierTree idt = (IdentifierTree)expression;
idName = idt.getName();
}
if (idName != null) {
if (idName.equals(type.getSimpleName())) {
return null;
}
if (idName.equals(type.getQualifiedName())) {
return null;
}
}
Element used = info.getTrees().getElement(treePath);
if (used == null || !used.getModifiers().contains(Modifier.STATIC)) {
return null;
}
if (isError(used)) {
return null;
}
if (used.getKind().isField()) {
kind[0] = 0;
} else {
if (used.getKind() == ElementKind.METHOD) {
kind[0] = 1;
} else {
kind[0] = 2;
}
}
simpleName[0] = used.getSimpleName().toString();
return new FixImpl(info, expr, type).toEditorFix();
}
private static boolean isError(Element e) {
if (e == null) {
return true;
}
if (e.getKind() != ElementKind.CLASS) {
return false;
}
TypeMirror type = ((TypeElement) e).asType();
return type == null || type.getKind() == TypeKind.ERROR;
}
@TriggerTreeKind(Kind.MEMBER_SELECT)
public static List run(HintContext ctx) {
CompilationInfo compilationInfo = ctx.getInfo();
TreePath treePath = ctx.getPath();
int[] span = new int[2];
int[] kind = new int[1];
String[] simpleName = new String[1];
Fix fix = computeFixes(compilationInfo, treePath, span, kind, simpleName);
if (fix == null) {
return null;
}
ErrorDescription ed = ErrorDescriptionFactory.forName(
ctx,
ctx.getPath(),
NbBundle.getMessage(StaticAccess.class, "MSG_StaticAccess", kind[0], simpleName[0]), // NOI18N
fix
);
return Collections.singletonList(ed);
}
static final class FixImpl extends JavaFix {
private final ElementHandle desiredType;
public FixImpl(CompilationInfo info, TreePath expr, TypeElement desiredType) {
super(info, expr);
this.desiredType = ElementHandle.create(desiredType);
}
public String getText() {
return NbBundle.getMessage(DoubleCheck.class, "MSG_StaticAccessText"); // NOI18N
}
@Override
protected void performRewrite(TransformationContext ctx) {
WorkingCopy wc = ctx.getWorkingCopy();
TreePath tp = ctx.getPath();
Element element = desiredType.resolve(wc);
if (element == null) {
Logger.getLogger("org.netbeans.modules.java.hints").log(Level.INFO, "Cannot resolve target element.");
return;
}
ExpressionTree idt = wc.getTreeMaker().QualIdent(element);
wc.rewrite(tp.getLeaf(), idt);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy