package org.antlr.intellij.plugin.templates;

import com.intellij.codeInsight.template.TemplateContextType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
import org.antlr.intellij.plugin.ANTLRv4Language;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public abstract class ANTLRLiveTemplateContext extends TemplateContextType {
	public ANTLRLiveTemplateContext(@NotNull @NonNls String id,
									@NotNull String presentableName,
									@Nullable Class<? extends TemplateContextType> baseContextType)
	{
		super(id, presentableName, baseContextType);
	}

	protected abstract boolean isInContext(@NotNull PsiFile file, @NotNull PsiElement element, int offset);

	@Override
	public boolean isInContext(@NotNull PsiFile file, int offset) {
		// offset is where cursor or insertion point is I guess
		if ( !PsiUtilBase.getLanguageAtOffset(file, offset).isKindOf(ANTLRv4Language.INSTANCE) ) {
			return false;
		}
		if ( offset==file.getTextLength() ) { // allow at EOF
			offset--;
		}
		PsiElement element = file.findElementAt(offset);

//		System.out.println("element " + element +", text="+element.getText());

//		if ( element!=null &&
//			(element.getText().endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)||
//			 element.getText().endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER)) )
//		{
//			// i hate this DUMMY_IDENTIFIER thing!!!!!!!!
//			return false;
//		}

		if ( element==null ) {
			return false;
		}

		return isInContext(file, element, offset);
	}
}

package org.antlr.intellij.plugin.templates;

import com.intellij.codeInsight.template.TemplateContextType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
import org.antlr.intellij.plugin.ANTLRv4Language;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public abstract class ANTLRLiveTemplateContext extends TemplateContextType {
	public ANTLRLiveTemplateContext(@NotNull @NonNls String id,
									@NotNull String presentableName,
									@Nullable Class<? extends TemplateContextType> baseContextType)
	{
		super(id, presentableName, baseContextType);
	}

	protected abstract boolean isInContext(@NotNull PsiFile file, @NotNull PsiElement element, int offset);

	@Override
	public boolean isInContext(@NotNull PsiFile file, int offset) {
		// offset is where cursor or insertion point is I guess
		if ( !PsiUtilBase.getLanguageAtOffset(file, offset).isKindOf(ANTLRv4Language.INSTANCE) ) {
			return false;
		}
		if ( offset==file.getTextLength() ) { // allow at EOF
			offset--;
		}
		PsiElement element = file.findElementAt(offset);

//		String trace = DebugUtil.currentStackTrace();
//		System.out.println("isInContext: element " + element +", text="+element.getText());
//		System.out.println(trace);

//		if ( element!=null &&
//			(element.getText().endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)||
//			 element.getText().endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER)) )
//		{
//			// i hate this DUMMY_IDENTIFIER thing!!!!!!!!
//			return false;
//		}

		if ( element==null ) {
			return false;
		}

		return isInContext(file, element, offset);
	}
}

add but comment out debug for jetbrains concerning too many calls to isInContext.