| /* |
| * 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.declarative; |
| |
| import com.sun.source.util.TreePath; |
| import java.lang.reflect.Method; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicReference; |
| import javax.lang.model.type.TypeMirror; |
| import org.netbeans.api.java.source.CompilationInfo; |
| import org.netbeans.modules.java.hints.declarative.conditionapi.Context; |
| import org.netbeans.modules.java.hints.declarative.conditionapi.Variable; |
| |
| /** |
| * |
| * @author lahvac |
| */ |
| public abstract class Condition { |
| |
| public final boolean not; |
| |
| private Condition(boolean not) { |
| this.not = not; |
| } |
| |
| public abstract boolean holds(Context ctx, boolean global); |
| |
| @Override |
| public abstract String toString(); |
| |
| public static final class Instanceof extends Condition { |
| |
| public final String variable; |
| public final String constraint; |
| public final int[] constraintSpan; |
| |
| public Instanceof(boolean not, String variable, String constraint, int[] constraintSpan) { |
| super(not); |
| this.variable = variable; |
| this.constraint = constraint; |
| this.constraintSpan = constraintSpan; |
| } |
| |
| @Override |
| public boolean holds(Context ctx, boolean global) { |
| TreePath boundTo = APIAccessor.IMPL.getSingleVariable(ctx, new Variable(variable)); |
| |
| if (boundTo == null) { |
| throw new IllegalStateException(); |
| } |
| |
| CompilationInfo info = APIAccessor.IMPL.getHintContext(ctx).getInfo(); |
| TypeMirror realType = info.getTrees().getTypeMirror(boundTo); |
| TypeMirror designedType = Hacks.parseFQNType(info, constraint); |
| |
| return not ^ info.getTypes().isSubtype(realType, designedType); |
| } |
| |
| @Override |
| public String toString() { |
| return "(INSTANCEOF " + (not ? "!" : "") + variable + "/" + constraint + ")"; |
| } |
| |
| } |
| |
| public static final class MethodInvocation extends Condition { |
| |
| private final String methodName; |
| private final Map<? extends String, ? extends ParameterKind> params; |
| private final MethodInvocationContext mic; |
| private final AtomicReference<Method> toCall = new AtomicReference<Method>(); |
| |
| public MethodInvocation(boolean not, String methodName, Map<? extends String, ? extends ParameterKind> params, MethodInvocationContext mic) { |
| super(not); |
| this.methodName = methodName; |
| this.params = params; |
| this.mic = mic; |
| } |
| |
| @Override |
| public boolean holds(Context ctx, boolean global) { |
| if (toCall.get() == null) { |
| //not linked yet? |
| if (!link()) { |
| throw new IllegalStateException(); |
| } |
| } |
| |
| return mic.invokeMethod(ctx, toCall.get(), params) ^ not; |
| } |
| |
| boolean link() { |
| Method m = mic.linkMethod(methodName, params); |
| |
| toCall.set(m); |
| |
| return m != null; |
| } |
| |
| @Override |
| public String toString() { |
| return "(METHOD_INVOCATION " + (not ? "!" : "") + ":" + methodName + "(" + params.toString() + "))"; |
| } |
| |
| public enum ParameterKind { |
| VARIABLE, |
| STRING_LITERAL, |
| ENUM_CONSTANT; |
| } |
| } |
| |
| public static final class False extends Condition { |
| |
| public False() { |
| super(false); |
| } |
| |
| @Override |
| public boolean holds(Context ctx, boolean global) { |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "(FALSE)"; |
| } |
| } |
| |
| public static final class Otherwise extends Condition { |
| |
| public Otherwise() { |
| super(false); |
| } |
| |
| @Override |
| public boolean holds(Context ctx, boolean global) { |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "(OTHERWISE)"; |
| } |
| } |
| |
| } |