GPUB: sync with GK 1.3.1 (hooks)

This commit is contained in:
Gregory.Shrago
2016-05-12 00:32:31 +03:00
parent 02c7c658e8
commit ada0d9eeb1
@@ -39,6 +39,7 @@ import com.intellij.util.Function;
import com.intellij.util.PairProcessor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.LimitedPool;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -92,6 +93,59 @@ public class GeneratedParserUtilBase {
}
};
public interface Hook<T> {
@Contract("_,null,_->null")
PsiBuilder.Marker run(PsiBuilder builder, PsiBuilder.Marker marker, T param);
}
public static final Hook<WhitespacesAndCommentsBinder> LEFT_BINDER =
new Hook<WhitespacesAndCommentsBinder>() {
@Override
public PsiBuilder.Marker run(PsiBuilder builder,
PsiBuilder.Marker marker,
WhitespacesAndCommentsBinder param) {
if (marker != null) marker.setCustomEdgeTokenBinders(param, null);
return marker;
}
};
public static final Hook<WhitespacesAndCommentsBinder> RIGHT_BINDER =
new Hook<WhitespacesAndCommentsBinder>() {
@Override
public PsiBuilder.Marker run(PsiBuilder builder,
PsiBuilder.Marker marker,
WhitespacesAndCommentsBinder param) {
if (marker != null) marker.setCustomEdgeTokenBinders(null, param);
return marker;
}
};
public static final Hook<WhitespacesAndCommentsBinder[]> WS_BINDERS =
new Hook<WhitespacesAndCommentsBinder[]>() {
@Override
public PsiBuilder.Marker run(PsiBuilder builder,
PsiBuilder.Marker marker,
WhitespacesAndCommentsBinder[] param) {
if (marker != null) marker.setCustomEdgeTokenBinders(param[0], param[1]);
return marker;
}
};
public static final Hook<String> LOG_HOOK = new Hook<String>() {
@Override
public PsiBuilder.Marker run(PsiBuilder builder, PsiBuilder.Marker marker, String param) {
PsiBuilderImpl.ProductionMarker m = (PsiBuilderImpl.ProductionMarker)marker;
int start = m == null ? builder.getCurrentOffset() : m.getStartOffset();
int end = m == null ? start : m.getEndOffset();
String prefix = "[" + start + ", " + end + "]" + (m == null ? "" : " " + m.getTokenType());
builder.mark().error(prefix + ": " + param);
return marker;
}
};
public static boolean eof(PsiBuilder builder, int level) {
return builder.eof();
}
@@ -481,9 +535,35 @@ public class GeneratedParserUtilBase {
close_frame_impl_(state, frame, builder, marker, elementType, result, pinned);
exit_section_impl_(state, frame, builder, elementType, result, pinned, eatMore);
}
if (state.hooks != null) {
run_hooks_impl_(builder, state, level, pinned || result ? elementType : null);
}
state.FRAMES.recycle(frame);
}
public static <T> void register_hook_(PsiBuilder builder, int level, Hook<T> hook, T param) {
ErrorState state = ErrorState.get(builder);
state.hooks = Hooks.concat(hook, param, level, state.hooks);
}
public static <T> void register_hook_(PsiBuilder builder, int level, Hook<T[]> hook, T... param) {
ErrorState state = ErrorState.get(builder);
state.hooks = Hooks.concat(hook, param, level, state.hooks);
}
private static void run_hooks_impl_(PsiBuilder builder, ErrorState state, int level, @Nullable IElementType elementType) {
PsiBuilder.Marker marker = elementType == null ? null : (PsiBuilder.Marker)builder.getLatestDoneMarker();
if (elementType != null && marker == null) {
builder.error("No expected done marker at offset " + builder.getCurrentOffset());
}
while (state.hooks != null && state.hooks.level >= level) {
if (state.hooks.level == level) {
marker = ((Hook<Object>)state.hooks.hook).run(builder, marker, state.hooks.param);
}
state.hooks = state.hooks.next;
}
}
private static void exit_section_impl_(ErrorState state,
Frame frame,
PsiBuilder builder,
@@ -831,6 +911,7 @@ public class GeneratedParserUtilBase {
int predicateCount;
boolean predicateSign = true;
boolean suppressErrors;
Hooks<?> hooks;
public Frame currentFrame;
public CompletionState completionState;
@@ -1042,6 +1123,24 @@ public class GeneratedParserUtilBase {
}
}
private static class Hooks<T> {
final Hook<T> hook;
final T param;
final int level;
final Hooks<?> next;
Hooks(Hook<T> hook, T param, int level, Hooks next) {
this.hook = hook;
this.param = param;
this.level = level;
this.next = next;
}
static <E> Hooks<E> concat(Hook<E> hook, E param, int level, Hooks<?> hooks) {
return new Hooks<E>(hook, param, level, hooks);
}
}
private static final int MAX_CHILDREN_IN_TREE = 10;
public static boolean parseAsTree(ErrorState state, final PsiBuilder builder, int level, final IElementType chunkType,