All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.spi.java.hints.MatcherUtilities 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.spi.java.hints;

import com.sun.source.tree.BlockTree;
import com.sun.source.tree.Scope;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.lang.model.type.TypeMirror;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.modules.java.hints.spiimpl.Utilities;
import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompiler;
import org.netbeans.api.java.source.matching.Matcher;
import org.netbeans.api.java.source.matching.Occurrence;
import org.netbeans.api.java.source.matching.Pattern;

/**XXX: cancelability
 * TODO: needed?
 *
 * @author lahvac
 */
public class MatcherUtilities {

    public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern) {
        return matches(ctx, variable, pattern, null, null, null);
    }

    public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern, boolean fillInVariablesHack) {
        return matches(ctx, variable, pattern, ctx.getVariables(), ctx.getMultiVariables(), ctx.getVariableNames(), 
                fillInVariablesHack ? ctx.getConstraints() : Map.of());
    }

    public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern, Map outVariables, Map> outMultiVariables, Map outVariables2Names) {
        return matches(ctx, variable, pattern, outVariables, outMultiVariables, outVariables2Names, Map.of());
    }

    public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern, Map outVariables, 
                        Map> outMultiVariables, Map outVariables2Names, Map variable2Type) {
        Pattern p = PatternCompiler.compile(ctx.getInfo(), pattern, variable2Type, List.of());
        Map variables = new HashMap<>(ctx.getVariables());
        Map> multiVariables = new HashMap<>(ctx.getMultiVariables());
        Map variables2Names = new HashMap<>(ctx.getVariableNames());
        Iterable occurrences = Matcher.create(ctx.getInfo())
                                                            .setCancel(new AtomicBoolean())
                                                            .setPresetVariable(variables, multiVariables, variables2Names)
                                                            .setSearchRoot(variable)
                                                            .setTreeTopSearch()
                                                            .match(p);

        if (occurrences.iterator().hasNext()) {
            Occurrence od = occurrences.iterator().next();
            outVariables(outVariables, od.getVariables(), ctx.getVariables());
            outVariables(outMultiVariables, od.getMultiVariables(), ctx.getMultiVariables());
            outVariables(outVariables2Names, od.getVariables2Names(), ctx.getVariableNames());

            return true;
        }

        return false;
    }

    public static boolean matches(@NonNull HintContext ctx, @NonNull Collection variable, @NonNull String pattern, Map outVariables, Map> outMultiVariables, Map outVariables2Names) {
        Scope s = Utilities.constructScope(ctx.getInfo(), Map.of());
        Tree  patternTree = Utilities.parseAndAttribute(ctx.getInfo(), pattern, s);
        List patternTrees;

        if (Utilities.isFakeBlock(patternTree)) {
            List statements = ((BlockTree) patternTree).getStatements();

            patternTrees = statements.subList(1, statements.size() - 1);
        } else {
            patternTrees = List.of(patternTree);
        }

        if (variable.size() != patternTrees.size()) return false;
        
        Map variables = new HashMap<>(ctx.getVariables());
        Map> multiVariables = new HashMap<>(ctx.getMultiVariables());
        Map variables2Names = new HashMap<>(ctx.getVariableNames());
        Iterator variableIt = variable.iterator();
        Iterator patternTreesIt = patternTrees.iterator();

        while (variableIt.hasNext() && patternTreesIt.hasNext()) {
            TreePath patternTreePath = new TreePath(new TreePath(ctx.getInfo().getCompilationUnit()), patternTreesIt.next());
            Pattern p = Pattern.createPatternWithFreeVariables(patternTreePath, Map.of());
            Iterable occurrences = Matcher.create(ctx.getInfo())
                                                                .setCancel(new AtomicBoolean())
                                                                .setPresetVariable(variables, multiVariables, variables2Names)
                                                                .setSearchRoot(variableIt.next())
                                                                .setTreeTopSearch()
                                                                .match(p);

            if (!occurrences.iterator().hasNext()) {
                return false;
            }

            Occurrence od = occurrences.iterator().next();

            variables = od.getVariables();
            multiVariables = od.getMultiVariables();
            variables2Names = od.getVariables2Names();
        }

        if (variableIt.hasNext() == patternTreesIt.hasNext()) {
            outVariables(outVariables, variables, ctx.getVariables());
            outVariables(outMultiVariables, multiVariables, ctx.getMultiVariables());
            outVariables(outVariables2Names, variables2Names, ctx.getVariableNames());

            return true;
        }

        return false;
    }

    private static  void outVariables(Map outMap, Map currentValues, Map origValues) {
        if (outMap == null) return;

        currentValues.keySet().removeAll(origValues.keySet());

        outMap.putAll(currentValues);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy