/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.lang.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager;
import gw.lang.parser.GosuParserFactory;
import gw.lang.parser.IGosuParser;
import gw.lang.parser.ISymbolTable;
import gw.lang.parser.ParserOptions;
import gw.lang.parser.exceptions.ParseResultsException;
import gw.lang.parser.exceptions.SymbolNotFoundException;
import gw.lang.parser.statements.IClassFileStatement;
import gw.lang.parser.statements.IClassStatement;
import gw.lang.reflect.IType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.gs.IGosuProgram;
import gw.lang.reflect.gs.ITemplateType;
import gw.lang.reflect.module.IModule;
import gw.plugin.ij.icons.GosuIcons;
import gw.plugin.ij.lang.GosuLanguage;
import gw.plugin.ij.lang.parser.GosuAstTransformer;
import gw.plugin.ij.lang.psi.api.IGosuPackageDefinition;
import gw.plugin.ij.lang.psi.api.statements.IGosuUsesStatementList;
import gw.plugin.ij.lang.psi.util.GosuPsiParseUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class GosuTemplateFileImpl extends AbstractGosuClassFileImpl {
public GosuTemplateFileImpl(@NotNull FileViewProvider viewProvider) {
super(viewProvider, GosuLanguage.instance());
}
@NotNull
@SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException"})
protected GosuTemplateFileImpl clone() {
return (GosuTemplateFileImpl) super.clone();
}
public ASTNode parse(@NotNull ASTNode chameleon) {
return GosuAstTransformer.instance().transformProgram(chameleon, (IGosuProgram) parseType(false)).getFirstChildNode();
}
public IGosuProgram parseType(String strClassName, String contents, int completionMarkerOffset) {
final IModule module = getModule();
TypeSystem.pushModule(module);
// DP: this line should execute outside the TS lock to avoid deadlock
final IGosuParser parser = createParser(contents);
TypeSystem.lock();
try {
refreshTheOldType();
ITemplateType templateType;
IClassFileStatement classFileStmt;
ISymbolTable snapshotSymbols = null;
IType ctxType = null;
try {
final ParserOptions options = new ParserOptions()
.withParser(parser)
.withFileContext(new ModuleFileContext(module, strClassName));
templateType = (ITemplateType) GosuParserFactory
.createProgramParser()
.parseTemplate(contents, parser.getSymbolTable(), options)
.getProgram();
classFileStmt = templateType.getClassStatement().getClassFileStatement();
} catch (ParseResultsException ex) {
classFileStmt = (IClassFileStatement) ex.getParsedElement();
IClassStatement classStatement = classFileStmt.getClassStatement();
templateType = classStatement != null ? (ITemplateType) classStatement.getGosuClass() : null;
SymbolNotFoundException issue = getExceptionWithSymbolTable(ex);
if (issue != null) {
snapshotSymbols = issue.getSymbolTable();
ctxType = issue.getExpectedType();
}
}
if (getOriginalFile().getVirtualFile() != null) {
final GosuClassParseData data = getParseData();
data.setClassFileStatement(classFileStmt);
data.setSource(contents);
if (isForComplection(contents)) {
data.setSnapshotSymbols(snapshotSymbols);
data.setContextType(ctxType);
}
}
return templateType;
} finally {
TypeSystem.unlock();
TypeSystem.popModule(module);
}
}
@Override
public void addImport(String qualifiedName) {
final PsiElement usesStmt = GosuPsiParseUtil.parseTemplateImport(qualifiedName, this);
final IGosuUsesStatementList uses = findChildByClass(IGosuUsesStatementList.class);
final PsiElement psiElement;
if (uses == null) {
psiElement = addAfter(usesStmt, findChildByClass(IGosuPackageDefinition.class));
} else {
psiElement = uses.add(usesStmt.getChildren()[0]);
}
CodeStyleManager.getInstance(getProject()).reformat(psiElement);
}
@Override
protected Icon getElementIcon(@IconFlags int flags) {
return GosuIcons.FILE_TEMPLATE;
}
}