Combined Module Root detection

Hi,

I'm developing a ECMA_SCRIPT_L4 based plugin, I'm at the point I want my project/modules be imported via the IDEA GUI, so, I extended ProjectStructureDetector, overrided createWizardSteps, overrided ModuleSourceRoot [1]
In the Wizard, I can see the module detected as my own SdkType and can see my custom SdkStep but the wizard continues trying to set a Flex SDK too,  what I don't want (I guess that's because the source files are ActionScript files).

I had a look to DetectedRootData.addRoot but it was difficult to see what happens, I can't debug it with local variables as I can't use IDEA CE because I use JavaScriptSupport, btw, if there's a way to get the local variables, don't hesitate to tell me :)

So, how can I instruct IDEA to use my Sdk only ? (I'm sorry if it's a noob question but that's my first plugin and I didn't find any doc on it and as I said, I can't debug it either)

Thanks,
-Fred

[1]
public class RandoriModuleSourceRoot extends DetectedProjectRoot
{
    public RandoriModuleSourceRoot(File directory)
    {
        super(directory);
    }


    @NotNull
    @Override
    public String getRootTypeName()
    {
        return "Randori module";
    }


    public DetectedProjectRoot combineWith(@NotNull DetectedProjectRoot root)
    {
        if (root == null)
            throw new IllegalArgumentException(
                    "Argument 0 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriModuleSourceRoot.combineWith must not be null");


        return this;
    }


    @Override
    public boolean canContainRoot(@NotNull DetectedProjectRoot root)
    {
        if (root == null)
            throw new IllegalArgumentException(
                    "Argument 0 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriModuleSourceRoot.canContainRoot must not be null");


        if (root instanceof RandoriModuleSourceRoot)
            return true;


        return false;
    }
}


Ce message a été modifié par: Frederic THOMAS

0
20 comments

So, a bit of updates, the canContainRoot function is never called and the combineWith function had to be like that [1] to make the wizard step relative to the source root detection be able to detect both the possible source roots but when I click Next, nothing happens (weird !!), if I click Next again, the libraries and modules steps are shown and at the end, it says No framework detected, so, I still don't know what to do :_|

-Fred

[1]
public DetectedProjectRoot combineWith(@NotNull DetectedProjectRoot root)
    {
        if (root == null)
            throw new IllegalArgumentException(
                    "Argument 0 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriModuleSourceRoot.combineWith must not be null");

        if (root instanceof RandoriModuleSourceRoot)
            return this;

        return null;
    }

0

Hi Frederic,

Is your project open-source? I can debug its processing locally against IJ UE sources.

Denis

0

I'm on a no public branch on 3/4 projects, the compiler, the plugin and the test project, so, I tryied to send you a zip (11Mb) with the setup intructions but it didn't work.

-Fred

0

Those classes are involved and I guess are enough to make a try on a default plugin project, I send you a smaller zip with for the test project :

I removed what I think is not needed from the plugin xml

Tell me if you need something else.

Thanks,,
-Fred

------------------------------------------------------------------------
<idea-plugin version="2" url="http://randoriframework.com">
    <name>Randori Compiler</name>
    <version>0.2.4</version>
    <idea-version since-build="123.169"/>

    <vendor>Teoti Graphix, LLC</vendor>
    <category>Framework integration</category>

    <depends>JavaScript</depends>

    <extensions defaultExtensionNs="com.intellij">

        <projectStructureDetector implementation="randori.plugin.projectStructure.detection.RandoriProjectStructureDetector"/>
        <sdkType implementation="randori.plugin.roots.RandoriSdkType"/>

        <moduleType id="RANDORI_MODULE"
                    implementationClass="randori.plugin.module.RandoriModuleType"
                    classpathProvider="true"/>

    </extensions>

</idea-plugin>



------------------------------------------------------------------------
package randori.plugin.module;

import javax.swing.*;

import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;

import icons.RandoriIcons;

import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleTypeManager;
import com.intellij.openapi.projectRoots.Sdk;

public class RandoriModuleType extends ModuleType<RandoriModuleBuilder>
{

    @NonNls
    private static final String MODULE_ID = "RANDORI_MODULE";

    public RandoriModuleType()
    {
        super(MODULE_ID);
    }

    public static RandoriModuleType getInstance()
    {
        return (RandoriModuleType) ModuleTypeManager.getInstance().findByID(
                MODULE_ID);
    }

    public static boolean isOfType(Module module)
    {
        return get(module) instanceof RandoriModuleType;
    }

    // create New Project
    @Override
    public RandoriModuleBuilder createModuleBuilder()
    {
        return new RandoriModuleBuilder();
    }

    @Override
    public String getName()
    {
        return "Randori Module";
    }

    @Override
    public String getDescription()
    {
        return "This module type is used to create Randori AS3 projects using the Randori JavaScript cross compiler";
    }

    @Override
    public Icon getBigIcon()
    {
        return RandoriIcons.Randori24;
    }

    @Override
    public Icon getNodeIcon(boolean isOpened)
    {
        return RandoriIcons.Randori16;
    }

    @Override
    public boolean isValidSdk(Module module, @Nullable Sdk projectSdk)
    {
        return super.isValidSdk(module, projectSdk);
    }
}

------------------------------------------------------------------------

package randori.plugin.projectStructure.detection;

import com.intellij.ide.util.DelegatingProgressIndicator;
import com.intellij.ide.util.importProject.LibrariesDetectionStep;
import com.intellij.ide.util.importProject.ModulesDetectionStep;
import com.intellij.ide.util.importProject.ProjectDescriptor;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder;
import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector;
import com.intellij.ide.util.projectWizard.importSources.util.CommonSourceRootDetectionUtil;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.javascript.JSTokenTypes;
import com.intellij.lang.javascript.JavaScriptSupportLoader;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.NullableFunction;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import randori.plugin.module.RandoriModuleBuilder;

import javax.swing.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
* @author: Frédéric THOMAS Date: 19/04/13 Time: 18:58
*/
public class RandoriProjectStructureDetector extends ProjectStructureDetector
{

    public static final NullableFunction<CharSequence, String> PACKAGE_NAME_FETCHER = new NullableFunction() {
        @Nullable
        @Override
        public String fun(Object o)
        {
            CharSequence charSequence = (CharSequence) o;
            Lexer lexer = ((ParserDefinition) LanguageParserDefinitions.INSTANCE
                    .forLanguage(JavaScriptSupportLoader.ECMA_SCRIPT_L4)).createLexer(null);
            lexer.start(charSequence);
            return RandoriProjectStructureDetector.readPackageName(charSequence, lexer);
        }
    };

    private static final TokenSet WHITESPACE_AND_COMMENTS = TokenSet.create(new IElementType[] {
            JSTokenTypes.WHITE_SPACE, JSTokenTypes.DOC_COMMENT, JSTokenTypes.C_STYLE_COMMENT,
            JSTokenTypes.END_OF_LINE_COMMENT });

    public static boolean isActionScriptFile(File file)
    {
        String extension = FileUtilRt.getExtension(file.getName());
        return JavaScriptSupportLoader.ECMA_SCRIPT_L4.equals(JavaScriptSupportLoader.getLanguageDialect(extension));
    }

    @NotNull
    @Override
    public DirectoryProcessingResult detectRoots(@NotNull File dir, @NotNull File[] children, @NotNull File base,
            @NotNull List<DetectedProjectRoot> result)
    {
        if (dir == null)
            throw new IllegalArgumentException(
                    "Argument 0 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriProjectStructureDetector.detectRoots must not be null");

        if (children == null)
            throw new IllegalArgumentException(
                    "Argument 1 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriProjectStructureDetector.detectRoots must not be null");

        if (base == null)
            throw new IllegalArgumentException(
                    "Argument 2 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriProjectStructureDetector.detectRoots must not be null");

        if (result == null)
            throw new IllegalArgumentException(
                    "Argument 3 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriProjectStructureDetector.detectRoots must not be null");


        for (File child : children)
        {
            if (child.isFile())
            {
                if (isActionScriptFile(child))
                {
                    Pair<File, String> root = CommonSourceRootDetectionUtil.IO_FILE
                            .suggestRootForFileWithPackageStatement(child, base, PACKAGE_NAME_FETCHER, true);
                    if (root != null)
                    {
                        result.add(new RandoriModuleSourceRoot(dir));
                        return DirectoryProcessingResult.skipChildrenAndParentsUpTo(root.getFirst());
                    }
                    else
                    {
                        return DirectoryProcessingResult.SKIP_CHILDREN;
                    }
                }
            }
        }
        return DirectoryProcessingResult.PROCESS_CHILDREN;
    }

    @Override
    public List<ModuleWizardStep> createWizardSteps(ProjectFromSourcesBuilder builder,
            ProjectDescriptor projectDescriptor, Icon stepIcon)
    {
        RandoriModuleInsight moduleInsight = new RandoriModuleInsight(new DelegatingProgressIndicator(),
                builder.getExistingModuleNames(), builder.getExistingProjectLibraryNames());

        List steps = new ArrayList();
        steps.add(new LibrariesDetectionStep(builder, projectDescriptor, moduleInsight, stepIcon,
                "reference.dialogs.new.project.fromCode.page1"));

        steps.add(new ModulesDetectionStep(this, builder, projectDescriptor, moduleInsight, stepIcon,
                "reference.dialogs.new.project.fromCode.page2"));

        steps.add(new RandoriSdkStep(builder.getContext(), new RandoriModuleBuilder()));
        return steps;
    }

    @Nullable
    public static String readPackageName(CharSequence charSequence, Lexer lexer)
    {
        skipWhiteSpaceAndComments(lexer);
        if (!JSTokenTypes.PACKAGE_KEYWORD.equals(lexer.getTokenType()))
        {
            return null;
        }
        lexer.advance();
        skipWhiteSpaceAndComments(lexer);

        return readQualifiedName(charSequence, lexer, false);
    }

    @Nullable
    static String readQualifiedName(CharSequence charSequence, Lexer lexer, boolean allowStar)
    {
        StringBuilder buffer = StringBuilderSpinAllocator.alloc();
        try
        {
            while ((lexer.getTokenType() == JSTokenTypes.IDENTIFIER)
                    || ((allowStar) && (lexer.getTokenType() != JSTokenTypes.MULT)))
            {
                buffer.append(charSequence, lexer.getTokenStart(), lexer.getTokenEnd());
                if (lexer.getTokenType() == JSTokenTypes.MULT)
                    break;
                lexer.advance();
                if (lexer.getTokenType() != JSTokenTypes.DOT)
                    break;
                buffer.append('.');
                lexer.advance();
            }
            String packageName = buffer.toString();
            String str1;
            if (StringUtil.endsWithChar(packageName, '.'))
                return null;
            return packageName;
        }
        finally
        {
            StringBuilderSpinAllocator.dispose(buffer);
        }
    }

    public static void skipWhiteSpaceAndComments(Lexer lexer)
    {
        while (WHITESPACE_AND_COMMENTS.contains(lexer.getTokenType()))
            lexer.advance();
    }
}


------------------------------------------------------------------------
package randori.plugin.projectStructure.detection;

import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
import org.jetbrains.annotations.NotNull;

import java.io.File;

/**
* @author: Frédéric THOMAS Date: 19/04/13 Time: 19:40
*/
public class RandoriModuleSourceRoot extends DetectedProjectRoot
{
    public RandoriModuleSourceRoot(File directory)
    {
        super(directory);
    }

    @NotNull
    @Override
    public String getRootTypeName()
    {
        return "Randori module";
    }

    public DetectedProjectRoot combineWith(@NotNull DetectedProjectRoot root)
    {
        if (root == null)
            throw new IllegalArgumentException(
                    "Argument 0 for @NotNull parameter of randori/plugin/projectStructure/detection/RandoriModuleSourceRoot.combineWith must not be null");

        if (root instanceof RandoriModuleSourceRoot)
            return this;

        return null;
    }
}

------------------------------------------------------------------------
package randori.plugin.projectStructure.detection;

import javax.swing.*;

import randori.plugin.ui.RandoriSdkComboBoxWithBrowseButton;

import com.intellij.ide.util.projectWizard.ModuleBuilder;

import com.intellij.ide.util.projectWizard.ModuleWizardStep;

import com.intellij.ide.util.projectWizard.WizardContext;

import com.intellij.openapi.projectRoots.Sdk;

import com.intellij.openapi.roots.ProjectRootManager;

import com.intellij.util.ui.UIUtil;

/**

* @author: Frédéric THOMAS Date: 19/04/13 Time: 20:44

*/

public class RandoriSdkStep extends ModuleWizardStep

{

    private final WizardContext context;

    private JPanel contentPane;

    private RandoriSdkComboBoxWithBrowseButton sdkCombo;

    private JLabel sdkLabel;

    public RandoriSdkStep(WizardContext context, ModuleBuilder moduleBuilder)

    {

        this.context = context;

        Sdk sdk = ProjectRootManager.getInstance(context.getProject()).getProjectSdk();

        /*if (sdk != null && moduleBuilder.isSuitableSdkType(sdk.getSdkType())) {

            // use project SDK

            return;

        }*/

        sdkLabel = new JLabel();

        sdkCombo = new RandoriSdkComboBoxWithBrowseButton(RandoriSdkComboBoxWithBrowseButton.RANDORI_SDK);

        sdkCombo.setSelectedSdkRaw(sdk.getName());

        contentPane = new JPanel();

        contentPane.add(sdkLabel);

        contentPane.add(sdkCombo);

    }

    @Override

    public JComponent getComponent()

    {

        this.sdkLabel.setLabelFor(this.sdkCombo.getChildComponent());

        String text = this.context.getProject() != null ? "Module &SDK:" : "Project &SDK:";

        this.sdkLabel.setText(UIUtil.removeMnemonic(text));

        this.sdkLabel.setDisplayedMnemonicIndex(UIUtil.getDisplayMnemonicIndex(text));

        return this.contentPane;

    }

    @Override

    public void updateDataModel()

    {

        this.context.setProjectJdk(this.sdkCombo.getSelectedSdk());

    }

}


------------------------------------------------------------------------

package randori.plugin.ui;

import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.projectRoots.*;
import com.intellij.openapi.projectRoots.ui.ProjectJdksEditor;
import com.intellij.openapi.roots.ui.configuration.ProjectJdksConfigurable;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.JdkListConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ComboboxWithBrowseButton;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import org.jetbrains.annotations.Nullable;
import randori.plugin.roots.RandoriSdkType;

/**
* @author: Frédéric THOMAS
* Date: 20/04/13
* Time: 08:39
*/
public class RandoriSdkComboBoxWithBrowseButton extends ComboboxWithBrowseButton
{
    public static final Condition<Sdk> RANDORI_SDK = new Condition() {
        @Override
        public boolean value(Object o) {
            Sdk sdk = (Sdk) o;
            return (sdk != null) && ((sdk.getSdkType() instanceof RandoriSdkType));
        }
    };

    public static final String BC_SDK_KEY = "BC SDK";
    private final Condition<Sdk> sdkFilter;
    private BCSdk bcSdk = new BCSdk();
    private boolean showBCSdk = false;

    public RandoriSdkComboBoxWithBrowseButton() {
        this(RANDORI_SDK);
    }

    public RandoriSdkComboBoxWithBrowseButton(Condition<Sdk> sdkFilter) {
        this.sdkFilter = sdkFilter;
        rebuildSdkListAndSelectSdk(null);

        final JComboBox sdkCombo = getComboBox();
        sdkCombo.setRenderer(new ListCellRendererWrapper()
        {
            public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) {
                if ((value instanceof RandoriSdkComboBoxWithBrowseButton.BCSdk)) {
                    Sdk sdk = ((RandoriSdkComboBoxWithBrowseButton.BCSdk)value).mySdk;
                    if (sdk == null) {
                        if (sdkCombo.isEnabled()) {
                            setText("<html>SDK set for the build configuration <font color='red'>[not set]</font></html>");
                            setIcon(null);
                        }
                        else {
                            setText("SDK set for the build configuration [not set]");
                            setIcon(null);
                        }
                    }
                    else {
                        setText("SDK set for the build configuration [" + sdk.getName() + "]");
                        setIcon(((SdkType)((RandoriSdkComboBoxWithBrowseButton.BCSdk)value).mySdk.getSdkType()).getIcon());
                    }
                }
                else if ((value instanceof String)) {
                    if (sdkCombo.isEnabled()) {
                        setText("<html><font color='red'>" + value + " [Invalid]</font></html>");
                        setIcon(null);
                    }
                    else {
                        setText(value + " [Invalid]");
                        setIcon(null);
                    }
                }
                else if ((value instanceof Sdk)) {
                    setText(((Sdk)value).getName());
                    setIcon(((SdkType)((Sdk)value).getSdkType()).getIcon());
                }
                else if (sdkCombo.isEnabled()) {
                    setText("<html><font color='red'>[none]</font></html>");
                }
                else {
                    setText("[none]");
                }
            }
        });
        addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Project project = (Project)PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
                if (project == null) {
                    project = ProjectManager.getInstance().getDefaultProject();
                }

                ProjectSdksModel sdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
                sdksModel = new RandoriSdkComboBoxWithBrowseButton.NonCommittingWrapper(sdksModel, JdkListConfigurable.getInstance(project));

                ProjectJdksEditor editor = new ProjectJdksEditor(null, RandoriSdkComboBoxWithBrowseButton.this, new ProjectJdksConfigurable(project, sdksModel));

                editor.show();
                if (editor.isOK()) {
                    Sdk selectedSdk = editor.getSelectedJdk();
                    if (RandoriSdkComboBoxWithBrowseButton.this.sdkFilter.value(selectedSdk)) {
                        RandoriSdkComboBoxWithBrowseButton.this.rebuildSdkListAndSelectSdk(selectedSdk);
                    }
                    else {
                        RandoriSdkComboBoxWithBrowseButton.this.rebuildSdkListAndSelectSdk(null);
                        if (selectedSdk != null)
                            Messages.showErrorDialog(RandoriSdkComboBoxWithBrowseButton.this, "SDK '" + selectedSdk.getName() + "' can not be selected here.\\nPlease select a Randori SDK.", "Select a Randori SDK");
                    }
                }
            }
        });
    }

    private void rebuildSdkListAndSelectSdk(@Nullable Sdk selectedSdk)
    {
        String previousSelectedSdkName = getSelectedSdkRaw();
        List sdkList = new ArrayList();

        if (this.showBCSdk) {
            sdkList.add(this.bcSdk);
        }

        Sdk[] sdks = ProjectJdkTable.getInstance().getAllJdks();
        for (Sdk sdk : sdks) {
            if (this.sdkFilter.value(sdk)) {
                sdkList.add(sdk);
            }
        }

        if (!sdkList.isEmpty())
        {
            Collections.sort(sdkList, new Comparator() {
                public int compare(Object sdk1, Object sdk2) {
                    if ((sdk1 == RandoriSdkComboBoxWithBrowseButton.this.bcSdk) && (sdk2 != RandoriSdkComboBoxWithBrowseButton.this.bcSdk)) return -1;
                    if ((sdk1 != RandoriSdkComboBoxWithBrowseButton.this.bcSdk) && (sdk2 == RandoriSdkComboBoxWithBrowseButton.this.bcSdk)) return 1;

                    if (((sdk1 instanceof Sdk)) && ((sdk2 instanceof Sdk))) {
                        SdkTypeId type1 = ((Sdk)sdk1).getSdkType();
                        SdkTypeId type2 = ((Sdk)sdk2).getSdkType();

                        if (type1 == type2) return -StringUtil.compareVersionNumbers(((Sdk)sdk1).getVersionString(), ((Sdk)sdk2).getVersionString());
                        if (type1 == RandoriSdkType.getInstance()) return -1;
                        if (type2 == RandoriSdkType.getInstance()) return 1;
                    }

                    return 0;
                }
            });
            getComboBox().setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(sdkList)));
            if (selectedSdk != null) {
                setSelectedSdkRaw(selectedSdk.getName(), false);
            }
            else if (previousSelectedSdkName != null)
                setSelectedSdkRaw(previousSelectedSdkName, false);
        }
        else
        {
            getComboBox().setModel(new DefaultComboBoxModel(new Object[] { null }));
        }
    }

    public void addComboboxListener(final Listener listener) {
        getComboBox().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                listener.stateChanged();
            }
        });
        getComboBox().addPropertyChangeListener("model", new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                listener.stateChanged();
            }
        });
    }

    @Nullable
    public Sdk getSelectedSdk() {
        Object selectedItem = getComboBox().getSelectedItem();

        if ((selectedItem instanceof BCSdk)) {
            return ((BCSdk)selectedItem).mySdk;
        }
        if ((selectedItem instanceof Sdk)) {
            return (Sdk)selectedItem;
        }

        return null;
    }

    public String getSelectedSdkRaw()
    {
        Object selectedItem = getComboBox().getSelectedItem();

        if ((selectedItem instanceof BCSdk)) {
            return "BC SDK";
        }
        if ((selectedItem instanceof Sdk)) {
            return ((Sdk)selectedItem).getName();
        }
        if ((selectedItem instanceof String)) {
            return (String)selectedItem;
        }

        return "";
    }

    public void setSelectedSdkRaw(String sdkName)
    {
        setSelectedSdkRaw(sdkName, true);
    }

    private void setSelectedSdkRaw(String sdkName, boolean addErrorItemIfSdkNotFound) {
        JComboBox combo = getComboBox();

        if ("BC SDK".equals(sdkName)) {
            combo.setSelectedItem(this.bcSdk);
            return;
        }

        for (int i = 0; i < combo.getItemCount(); i++) {
            Object item = combo.getItemAt(i);
            if (((item instanceof Sdk)) && (((Sdk)item).getName().equals(sdkName))) {
                combo.setSelectedItem(item);
                return;
            }

        }

        if (addErrorItemIfSdkNotFound) {
            List items = new ArrayList();
            items.add(sdkName);
            for (int i = 0; i < combo.getItemCount(); i++) {
                Object item = combo.getItemAt(i);
                if (!(item instanceof String)) {
                    items.add(item);
                }
            }
            combo.setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(items)));
        }
    }

    public void showBCSdk(boolean showBCSdk) {
        if (this.showBCSdk != showBCSdk) {
            this.showBCSdk = showBCSdk;
            Object selectedItem = getComboBox().getSelectedItem();
            rebuildSdkListAndSelectSdk(null);
            if ((selectedItem instanceof String))
                setSelectedSdkRaw((String)selectedItem, true);
        }
    }

    public void setBCSdk(Sdk sdk)
    {
        if (sdk != this.bcSdk.mySdk)
            this.bcSdk.mySdk = sdk;
    }

    private static class NonCommittingWrapper extends ProjectSdksModel {
        private final ProjectSdksModel myOriginal;
        private JdkListConfigurable myConfigurable;

        public NonCommittingWrapper(ProjectSdksModel original, JdkListConfigurable configurable) {
            this.myOriginal = original;
            this.myConfigurable = configurable;
        }

        public void apply() throws ConfigurationException {
            apply(null);
        }

        public void apply(@Nullable MasterDetailsComponent configurable) throws ConfigurationException {
            this.myConfigurable.reset();
        }

        public void reset(@Nullable Project project)
        {
        }

        public void addListener(SdkModel.Listener listener) {
            this.myOriginal.addListener(listener);
        }

        public void removeListener(SdkModel.Listener listener) {
            this.myOriginal.removeListener(listener);
        }

        public SdkModel.Listener getMulticaster() {
            return this.myOriginal.getMulticaster();
        }

        public Sdk[] getSdks() {
            return this.myOriginal.getSdks();
        }

        public Sdk findSdk(String sdkName) {
            return this.myOriginal.findSdk(sdkName);
        }

        public void disposeUIResources()
        {
        }

        public HashMap<Sdk, Sdk> getProjectSdks() {
            return this.myOriginal.getProjectSdks();
        }

        public boolean isModified() {
            return this.myOriginal.isModified();
        }

        public void removeSdk(Sdk editableObject) {
            this.myOriginal.removeSdk(editableObject);
        }

        public void createAddActions(DefaultActionGroup group, JComponent parent, Consumer<Sdk> updateTree, @Nullable Condition<SdkTypeId> filter)
        {
            this.myOriginal.createAddActions(group, parent, updateTree, filter);
        }

        public void doAdd(JComponent parent, SdkType type, Consumer<Sdk> updateTree) {
            this.myOriginal.doAdd(parent, type, updateTree);
        }

        public void addSdk(Sdk sdk) {
            this.myOriginal.addSdk(sdk);
        }

        public void doAdd(Sdk newSdk, @Nullable Consumer<Sdk> updateTree) {
            this.myOriginal.doAdd(newSdk, updateTree);
        }

        public Sdk findSdk(@Nullable Sdk modelJdk) {
            return this.myOriginal.findSdk(modelJdk);
        }

        public Sdk getProjectSdk() {
            return this.myOriginal.getProjectSdk();
        }

        public void setProjectSdk(Sdk projectSdk) {
            this.myOriginal.setProjectSdk(projectSdk);
        }

        public boolean isInitialized() {
            return this.myOriginal.isInitialized();
        }
    }

    private static class BCSdk
    {
        private Sdk mySdk;
    }

    public static abstract interface Listener
    {
        public abstract void stateChanged();
    }
}

------------------------------------------------------------------------

package randori.plugin.module;

import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import randori.plugin.roots.RandoriSdkType;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
* @author Michael Schmalle
*/
public class RandoriModuleBuilder extends JavaModuleBuilder
{
    // Pair<Source Path, Package Prefix>
    private List<Pair<String, String>> mySourcePaths;

    //private final List<Pair<String, String>> myModuleLibraries = new ArrayList<Pair<String, String>>();

    @Override
    public void setupRootModel(ModifiableRootModel rootModel)
            throws ConfigurationException
    {
        // adds the project/module's root as a content entry, this allows /generated
        // etc. to be seen in the project explorer
        ContentEntry contentEntry = doAddContentEntry(rootModel);

        if (contentEntry != null)
        {
            final List<Pair<String, String>> sourcePaths = getSourcePaths();

            if (sourcePaths != null)
            {
                for (final Pair<String, String> sourcePath : sourcePaths)
                {
                    String first = sourcePath.first;
                    new File(first).mkdirs();
                    final VirtualFile sourceRoot = LocalFileSystem
                            .getInstance().refreshAndFindFileByPath(
                                    FileUtil.toSystemIndependentName(first));
                    if (sourceRoot != null)
                    {
                        contentEntry.addSourceFolder(sourceRoot, false,
                                sourcePath.second);
                    }
                }
            }
        }

        List<Sdk> sdks = ProjectJdkTable.getInstance().getSdksOfType(
                RandoriSdkType.getInstance());
        if (sdks.size() > 0)
        {
            rootModel.setSdk(sdks.get(0));
        }

        //        // copy the files to generated
        //        VirtualFile randoriJS = sdkRoot.findFileByRelativePath("src/Randori.js");
        //        VirtualFile guiceJS = sdkRoot.findFileByRelativePath("src/RandoriGuiceJS.js");
        //        VirtualFile newRandoriJS = newFile;
        //        VirtualFile newRandoriGuiceJS = newFile;
        //        randoriJS.copy(this, newRandoriJS, "Randori.js");
        //        randoriJS.copy(this, newRandoriGuiceJS, "RandoriGuiceJS.js");
    }

    @Override
    public List<Pair<String, String>> getSourcePaths()
    {
        if (mySourcePaths == null)
        {
            final List<Pair<String, String>> paths = new ArrayList<Pair<String, String>>();
            @NonNls
            final String path = getContentEntryPath() + File.separator + "src";
            new File(path).mkdirs();
            paths.add(Pair.create(path, ""));
            return paths;
        }
        return mySourcePaths;
    }

    @Override
    public void setSourcePaths(List<Pair<String, String>> sourcePaths)
    {
        mySourcePaths = sourcePaths != null ? new ArrayList<Pair<String, String>>(
                sourcePaths) : null;
    }

    @Override
    public void addSourcePath(Pair<String, String> sourcePathInfo)
    {
        if (mySourcePaths == null)
        {
            mySourcePaths = new ArrayList<Pair<String, String>>();
        }
        mySourcePaths.add(sourcePathInfo);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public ModuleType getModuleType()
    {
        return RandoriModuleType.getInstance();
    }

    @Override
    public boolean isSuitableSdkType(SdkTypeId sdkType)
    {
        return RandoriSdkType.getInstance() == sdkType;
    }
}

Edit: adding a missing class



Attachment(s):
HMSS.zip
0

Denis,

The test project will need the sdk, it can be found here once the test project launched, try to import the "importedModule"

I'm sorry for the heavy setup, I would understand it is too much, I tried to send you a zip with everything inside but it failed 3 times.

-Fred

0

Denis,

Unfortunately I tried with the only classes I gave you and I can't run the project :(

The only way I can see for you to debug it is to checkout the compiler, sdk, plugin from https://github.com/RandoriAS then add the classes I gave you and run the test project from the zip I sent.

-Fred

0

Ok, will try that tomorrow or the next day after tomorrow

Denis

0

Denis,

Ok thanks, but if you know a simple way for me to send you a 11Mb zip, you won't have the burden to do all this setup, I would send you everything.

-Fred

0

Well, you can just email it to me at denis.zhdanov@jetbrains.com

Denis

0

Done !

Thank :)
-Fred

0

Hi Denis,

A bit of updates.

It took me yesterday and today to figure out what was missing for the "Next" button issue relative to the libraries in the import wizard:

1- My RandoriModuleSourceRoot was extending DetectedProjectRoot  instead of DetectedSourceRoot
2- I had to implement a RandoriLibraryType, RandoriLibraryRootsDetector and all the needed sub detectors + RandoriLibraryRootsComponentDescriptor

At the end, I can import a module, even if in the last step, the wizard tells me "No framework detected", have you got an idea why ?

The point is I would like to avoid the use of the FlexSupport because:

1- The SWCs (AS Libs) we use doesn't contains and should not contains MXML
2- The SWCs are packed into a bundle with some JS (For info, this plugin allows to write buisiness logic in AS and compile in JS, the user can use and create librairies which are packed into RBL files wherein there are the AS compiled (SWC) and the JS output)

So, I wonder, is it possible to get ride of the FlexSupport and still be able to map the class definitions from the RBL->SWCs to the internal symbol table ?

-Fred
PS: Do you want me to send you the updated plugin ?

0

Hi Frederic,

Opened the project you sent me earlier, made RandoriModuleSourceRoot extend DetectedSourceRoot and started 'import module' procedure. Am I right understanding that you experience two problems with it at the moment:

  • 'no framework is detected' at the last wizard step;
  • flex support is somehow registered at the module;


Regarding the first one - debugging shows that the last step (FrameworkDetectionStep) collects module content roots and feeds FrameworkDetectionProcessor.processRoots() by them. No framework is detected there. Not sure what is the expected result.

Regarding the second one - I don't see any flash/flex stuff to be applied to the module - check the screencast - https://dl.dropboxusercontent.com/u/1648086/video/import.m4v

Denis

0

Hi Denis,

My bad so, thanks for reminding me the Framework step is linked to the Facets ?:|

Now, what regarding how it is possible to select and have code completion on SWC libraries symbols from the inside of a RBL (a zipped evelop) ?

I know how to open and read the SWC catalog to get the class packages from the RBLs but then what ? What is the mechanism involved that gives IDEA the ability to get the symbols from those SWCs ? what classes should I hook/extend to make IDEA looking in the RBLs->SWCs instead of in the SWCs directly ?

I have to admit I didn't get the all process, actually, it seems to me that all the classes involved in that process are in the JavaScript support but I might be wrong because as soon as I remove the Flex plugin, the SWCs symbols are not found anymore, in the editor, everything is in red.

Can you give any help/directions on that ?

Thanks,
-Fred

0

Sorry, I'm far from flash/flex development :(

Will ask a competent engineer to comment

Denis

0

Denis,

Ok, thank you very much :)

Btw, I don't get everything yet but I realized it will be difficult even not possible for me to avoid the usage of the Flex Support, even though the class I need to get the SWC->library.swf interfaces is FlexImporter.buildInterfaceFromStream is in the JavaScript plugin, I guess the SWC file type itself is registered as JSFileElementType in the Flex plugin.

So, if I'm not wrong, I thing I will have to understand how to:

1- Register a RBL as binary JSFileElementType
2- Find the good extension points / interfaces to implement to provide a stub where the inside SWC->library.swf can be parsed (and that's the blur here)

-Fred

Ce message a été modifié par: Frederic THOMAS

0

Hi, Fred,
so many text in this thread, I feel a bit embarrassed ;)
The topic seems to be very specific so we may continue discussion in private: alexander dot doroshko at jetbrains dot com.
I'm not sure I got everything mentioned in this thread, so let's start with some localized problem. As I understand the main problem now is resolving classes from .rbl files, right? Please send me rbl file sample.

0

Hi Alexander,

I just was wondering if you received private emails I sent you ?

Thanks,
-Fred

0

No, I didn't.
Try alexander dot doroshko at gmail.

0

Done ! at gmail dot com

-Fred

0

Please sign in to leave a comment.