/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.runner; import com.google.common.base.Strings; import com.intellij.execution.CantRunException; import com.intellij.execution.configurations.JavaParameters; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.util.PsiTreeUtil; import gw.internal.gosu.parser.MetaType; import gw.lang.parser.IParsedElement; import gw.lang.parser.expressions.IEvalExpression; import gw.lang.parser.statements.IEvalStatement; import gw.lang.reflect.IType; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.gs.IGosuProgram; import gw.lang.reflect.module.IModule; import gw.plugin.ij.lang.psi.api.expressions.IGosuExpression; import gw.plugin.ij.lang.psi.impl.GosuScratchpadFileImpl; import gw.plugin.ij.util.GosuBundle; import gw.plugin.ij.util.GosuModuleUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class DefaultGosuRunner extends GosuProgramRunner { private JavaParameters _params; @Override public boolean isValidModule( @NotNull Module module ) { return true; // revisit: LibrariesUtil.hasGosuSdk( module ); } @Override public boolean ensureRunnerConfigured( @Nullable Module module, String confName, final Project project ) { if(confName.equals("Gosu Scratchpad.gsp") && hasCustomTypeInScratchpad( project )) { Messages.showMessageDialog(project, GosuBundle.message("scratchpad.debug.process"), GosuBundle.message("scratchpad.name"), Messages.getErrorIcon()); return false; } return true; } private static boolean hasCustomTypeInScratchpad( Project project ) { PsiElement psiElement = GosuScratchpadFileImpl.instance(project).getFirstChild(); PsiElementProcessor.CollectElements processor = new PsiElementProcessor.CollectElements(); PsiTreeUtil.processElements(psiElement, processor); boolean ret = false; for(PsiElement elem : processor.toArray()) { if( hasCustomType( elem ) ) { ret = true; break; } } return ret; } private static boolean hasCustomType( PsiElement element ) { if( element instanceof IGosuExpression ) { IParsedElement parsedElement = ((IGosuExpression)element).getParsedElement(); if( parsedElement == null ) { return false; } IType type = parsedElement.getReturnType(); if(type instanceof MetaType) { type = ((MetaType) type).getType(); } if(type.isArray()) { type = type.getComponentType(); } String packageName = type.getClass().getPackage().getName(); if( !packageName.startsWith( "gw.internal.gosu" ) && !packageName.startsWith( "gw.lang" )) { return true; } } return false; } public void configureCommandLine( Sdk gosuSdk, @NotNull JavaParameters params, @Nullable Module module, boolean tests, VirtualFile programFile, @NotNull GosuProgramRunConfiguration configuration ) throws CantRunException { _params = params; setToolsJar( params ); params.getVMParametersList().addParametersString( configuration._vmParams ); final String fqn = configuration.getFqn(); if( canExecuteFromBytecode( module, fqn ) ) { params.setMainClass( fqn ); } else { params.setMainClass( "gw.lang.Gosu" ); } IModule gosuModule = module == null ? GosuModuleUtil.getGlobalModule( configuration.getProject() ) : GosuModuleUtil.getModule( module ); GosuClasspathBuilder classpathBuilder = new GosuClasspathBuilder( gosuSdk, gosuModule, params ); classpathBuilder.fillClasspath(); if( !params.getClassPath().getPathsString().contains( "gosu-core-api" ) ) { addClasspathFromRootModel( module, tests, params ); } addProgramClasspath( classpathBuilder ); params.getProgramParametersList().add( FileUtil.toSystemDependentName( configuration._strProgramPath ) ); params.getProgramParametersList().addParametersString( configuration._strProgramParams ); } private boolean canExecuteFromBytecode( Module module, String fqn ) { if( Strings.isNullOrEmpty( fqn ) ) { return false; } IType type = TypeSystem.getByFullNameIfValid( fqn, GosuModuleUtil.getModule( module ) ); if( type instanceof IGosuProgram ) { IGosuProgram gsClass = (IGosuProgram)type; if( gsClass.getClassStatement().getContainedParsedElementsByType( IEvalExpression.class, null ) || gsClass.getClassStatement().getContainedParsedElementsByType( IEvalStatement.class, null ) ) { // A program with an eval statement can't be precompiled, therefore it can't be executed directly from bytecode on disk return false; } } return true; } private void addProgramClasspath( @NotNull GosuClasspathBuilder classpathBuilder ) { _params.getProgramParametersList().add( "-classpath" ); _params.getProgramParametersList().add( classpathBuilder.getProgramClasspath() ); } }