/*
* Copyright 2011-present Greg Shrago
*
* 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 org.intellij.grammar.livePreview;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.WhitespacesAndCommentsBinder;
import com.intellij.lang.WhitespacesBinders;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.grammar.parser.GeneratedParserUtilBase;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
/**
* @author gregsh
*/
public class LiveHooksHelper {
public static void registerHook(PsiBuilder builder, String name, String value) {
final GeneratedParserUtilBase.Hook hookObj = getHook(name);
if (hookObj == null) return;
Object hookParam = ObjectUtils.notNull(getHookParam(value), value);
GeneratedParserUtilBase.register_hook_(builder, (builder1, marker, param) -> {
try {
return hookObj.run(builder1, marker, param);
}
catch (Exception e) {
builder1.error("hook crashed: " + e.toString());
return marker;
}
}, hookParam);
}
private static final Map<String, Object> ourHooks = ContainerUtil.newHashMap();
private static final Map<String, Object> ourBinders = ContainerUtil.newHashMap();
static {
collectStaticFields(GeneratedParserUtilBase.class, GeneratedParserUtilBase.Hook.class, ourHooks);
collectStaticFields(WhitespacesBinders.class, WhitespacesAndCommentsBinder.class, ourBinders);
ourBinders.put("null", null);
}
public static GeneratedParserUtilBase.Hook getHook(String name) {
return (GeneratedParserUtilBase.Hook)ourHooks.get(name);
}
public static Object getHookParam(@NotNull String value) {
String[] args = value.trim().split("\\s*,\\s*");
if (args.length == 1) return ourBinders.get(args[0]);
Object[] res = new WhitespacesAndCommentsBinder[args.length];
for (int i = 0; i < args.length; i++) {
if (!ourBinders.containsKey(args[i])) return null;
res[i] = ourBinders.get(args[i]);
}
return res;
}
private static void collectStaticFields(Class<?> where, Class<?> what, Map<String, Object> result) {
for (Field field : where.getFields()) {
int m = field.getModifiers();
if ((m & Modifier.STATIC) != 0 && (m & Modifier.FINAL) != 0 && (m & Modifier.PUBLIC) != 0) {
if (what.isAssignableFrom(field.getType())) {
try {
result.put(field.getName(), field.get(null));
}
catch (IllegalAccessException ignored) {
}
}
}
}
}
}