/* * Copyright (C) 2013 The Android Open Source Project * * Licensed 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 com.android.tools.idea.editors.navigation.macros; import com.android.tools.idea.editors.navigation.Utilities; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; public class MultiMatch { public final PsiMethod macro; public final Map<String, PsiMethod> subMacros = new LinkedHashMap<String, PsiMethod>(); // make deterministic while prototyping public MultiMatch(PsiMethod macro) { this.macro = macro; } static MultiMatch create(Project project, String methodDefinition) { return new MultiMatch(Utilities.createMethodFromText(project, methodDefinition)); } public void addSubMacro(String name, PsiMethod macro) { subMacros.put(name, macro); } @Nullable public Bindings<PsiElement> match(PsiElement element) { Map<String, PsiElement> bindings = Unifier.match(macro, element); if (bindings == null) { return null; } Map<String, Map<String, PsiElement>> subBindings = new HashMap<String, Map<String, PsiElement>>(); for (Map.Entry<String, PsiMethod> entry : subMacros.entrySet()) { String name = entry.getKey(); PsiMethod template = entry.getValue(); Map<String, PsiElement> subBinding = Unifier.match(template, bindings.get(name)); if (subBinding == null) { return null; } subBindings.put(name, subBinding); } return new Bindings<PsiElement>(bindings, subBindings); } public String instantiate(Bindings<String> bindings) { Map<String, String> bb = bindings.bindings; for (Map.Entry<String, PsiMethod> entry : subMacros.entrySet()) { String name = entry.getKey(); PsiMethod template = entry.getValue(); bb.put(name, Instantiation.instantiate2(template, bindings.subBindings.get(name))); } return Instantiation.instantiate2(macro, bb); } public static class Bindings<T> { public final Map<String, T> bindings; public final Map<String, Map<String, T>> subBindings; Bindings(Map<String, T> bindings, Map<String, Map<String, T>> subBindings) { this.bindings = bindings; this.subBindings = subBindings; } Bindings() { this(new HashMap<String, T>(), new HashMap<String, Map<String, T>>()); } public T get(String key) { return bindings.get(key); } public void put(String key, T value) { bindings.put(key, value); } public T get(String key1, String key2) { Map<String, T> subBinding = subBindings.get(key1); return subBinding == null ? null : subBinding.get(key2); } public void put(String key1, String key2, T value) { Map<String, T> subBinding = subBindings.get(key1); if (subBinding == null) { subBindings.put(key1, subBinding = new HashMap<String, T>()); } subBinding.put(key2, value); } @Override public String toString() { return "Bindings{" + "bindings=" + bindings + ", subBindings=" + subBindings + '}'; } } }