/*
 * Copyright (C) 2016 Reece H. Dunn
 *
 * 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 uk.co.reecedunn.intellij.plugin.core.tests.parser;

import com.intellij.lang.ASTNode;
import com.intellij.lang.ParserDefinition;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.LeafElement;
import com.intellij.testFramework.LightVirtualFile;
import org.apache.xmlbeans.impl.common.IOUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;

public abstract class ParsingTestCase<File extends PsiFile> extends com.intellij.testFramework.ParsingTestCase {
    public ParsingTestCase(String fileExt, ParserDefinition... definitions) {
        super("", fileExt, definitions);
    }

    public String loadResource(String resource) {
        ClassLoader loader = ParsingTestCase.class.getClassLoader();
        InputStream stream = loader.getResourceAsStream(resource);
        StringWriter writer = new StringWriter();
        try {
            IOUtil.copyCompletely(new InputStreamReader(stream), writer);
        } catch (Exception e) {
            //
        }
        return writer.toString();
    }

    public LightVirtualFile createVirtualFile(@NonNls String name, String text) {
        LightVirtualFile file = new LightVirtualFile(name, myLanguage, text);
        file.setCharset(CharsetToolkit.UTF8_CHARSET);
        return file;
    }

    @SuppressWarnings("SameParameterValue")
    public FileViewProvider getFileViewProvider(@NotNull Project project, LightVirtualFile file, boolean physical) {
        final PsiManager manager = PsiManager.getInstance(project);
        final FileViewProviderFactory factory = LanguageFileViewProviders.INSTANCE.forLanguage(myLanguage);
        FileViewProvider viewProvider = factory != null ? factory.createFileViewProvider(file, myLanguage, manager, physical) : null;
        if (viewProvider == null) viewProvider = new SingleRootFileViewProvider(manager, file, physical);
        return viewProvider;
    }

    private void prettyPrintASTNode(@NotNull StringBuilder prettyPrinted, ASTNode node, int depth) {
        for (int i = 0; i != depth; ++i) {
            prettyPrinted.append("   ");
        }

        if (node instanceof FileElement) {
            prettyPrinted.append("FileElement");
        } else {
            String[] names = node.getPsi().getClass().getName().split("\\.");
            prettyPrinted.append(names[names.length - 1].replace("PsiImpl", "Impl"));
        }

        prettyPrinted.append('[');
        prettyPrinted.append(node.getElementType());
        prettyPrinted.append('(');
        prettyPrinted.append(node.getTextRange().getStartOffset());
        prettyPrinted.append(':');
        prettyPrinted.append(node.getTextRange().getEndOffset());
        prettyPrinted.append(')');
        prettyPrinted.append(']');
        if ((node instanceof LeafElement) || (node instanceof PsiErrorElement)) {
            prettyPrinted.append('(');
            prettyPrinted.append('\'');
            if (node instanceof PsiErrorElement) {
                PsiErrorElement error = (PsiErrorElement)node;
                prettyPrinted.append(error.getErrorDescription());
            } else {
                prettyPrinted.append(node.getText().replace("\n", "\\n"));
            }
            prettyPrinted.append('\'');
            prettyPrinted.append(')');
        }
        prettyPrinted.append('\n');

        for (ASTNode child : node.getChildren(null)) {
            prettyPrintASTNode(prettyPrinted, child, depth + 1);
        }
    }

    public String prettyPrintASTNode(File file) {
        StringBuilder prettyPrinted = new StringBuilder();
        prettyPrintASTNode(prettyPrinted, file.getNode(), 0);
        return prettyPrinted.toString();
    }

    @NotNull
    @SuppressWarnings("unchecked")
    public File parseFile(@NotNull LightVirtualFile file) {
        return (File)super.createFile(file);
    }

    @NotNull
    public File parseText(@NotNull String text) {
        return parseFile(createVirtualFile("testcase.xqy", text));
    }

    @NotNull
    public File parseResource(String resource) {
        return parseFile(createVirtualFile(resource, loadResource(resource)));
    }
}

@@ -847,16 +847,65 @@
 .psi.*;%0A
+import com.intellij.psi.impl.PsiFileFactoryImpl;%0A
 import c
@@ -942,32 +942,32 @@
 ee.FileElement;%0A
-
 import com.intel
@@ -1185,16 +1185,59 @@
 NotNull;
+%0Aimport org.jetbrains.annotations.Nullable;
 %0A%0Aimport
@@ -1431,24 +1431,71 @@
 gTestCase %7B%0A
+    private PsiFileFactoryImpl myFileFactory;%0A%0A
     public P
@@ -1556,24 +1556,24 @@
 initions) %7B%0A
-
         supe
@@ -1600,32 +1600,187 @@
 itions);%0A    %7D%0A%0A
+    @Override%0A    protected void setUp() throws Exception %7B%0A        super.setUp();%0A        myFileFactory = new PsiFileFactoryImpl(getPsiManager());%0A    %7D%0A%0A
     public Strin
@@ -4818,30 +4818,31 @@
    %7D%0A%0A    @N
-otN
 ull
+able
 %0A    @Suppre
@@ -4950,28 +4950,69 @@
 ile)
-super.createFile(fil
+myFileFactory.trySetupPsiForFile(file, myLanguage, true, fals
 e);%0A
@@ -5016,38 +5016,39 @@
 );%0A    %7D%0A%0A    @N
-otN
 ull
+able
 %0A    public File
@@ -5162,22 +5162,23 @@
 %0A%0A    @N
-otN
 ull
+able
 %0A    pub

Call trySetupPsiForFile directly. This requires creating a PsiFileFactoryImpl locally, as the parent class version is private.