com.perl5.lang.perl.psi.mixins.PerlSubDefinitionImplMixin.java Source code

Java tutorial

Introduction

Here is the source code for com.perl5.lang.perl.psi.mixins.PerlSubDefinitionImplMixin.java

Source

/*
 * Copyright 2015 Alexandr Evstigneev
 *
 * 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 com.perl5.lang.perl.psi.mixins;

import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.SmartList;
import com.perl5.lang.perl.idea.presentations.PerlItemPresentationSimple;
import com.perl5.lang.perl.idea.stubs.subsdefinitions.PerlSubDefinitionStub;
import com.perl5.lang.perl.psi.*;
import com.perl5.lang.perl.psi.properties.PerlLexicalScope;
import com.perl5.lang.perl.psi.utils.PerlSubArgument;
import com.perl5.lang.perl.psi.utils.PerlThisNames;
import com.perl5.lang.perl.psi.utils.PerlVariableType;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Created by hurricup on 25.05.2015.
 */
public abstract class PerlSubDefinitionImplMixin extends PerlSubBaseMixin<PerlSubDefinitionStub>
        implements PsiPerlSubDefinition {
    public PerlSubDefinitionImplMixin(@NotNull ASTNode node) {
        super(node);
    }

    public PerlSubDefinitionImplMixin(@NotNull PerlSubDefinitionStub stub, @NotNull IStubElementType nodeType) {
        super(stub, nodeType);
    }

    @Override
    public PerlLexicalScope getLexicalScope() {
        PerlLexicalScope scope = PsiTreeUtil.getParentOfType(this, PerlLexicalScope.class);
        assert scope != null;
        return scope;
    }

    @Override
    public boolean isMethod() {
        PerlSubDefinitionStub stub = getStub();
        if (stub != null)
            return stub.isMethod();

        if (super.isMethod())
            return true;

        List<PerlSubArgument> arguments = getSubArgumentsList();
        if (arguments.size() == 0)
            return false;

        PerlSubArgument firstArgument = arguments.get(0);

        return firstArgument.getArgumentType() == PerlVariableType.SCALAR
                && PerlThisNames.NAMES_SET.contains(firstArgument.getArgumentName());
    }

    @Override
    public String getSubArgumentsListAsString() {
        List<PerlSubArgument> subArguments = getSubArgumentsList();

        if (isMethod() && subArguments.size() > 0)
            subArguments.remove(0);

        int argumentsNumber = subArguments.size();

        List<String> argumentsList = new ArrayList<String>();
        for (PerlSubArgument argument : subArguments) {
            // todo we can mark optional subArguments after prototypes implementation
            argumentsList.add(argument.toStringShort());

            int compiledListSize = argumentsList.size();
            if (compiledListSize > 4 && argumentsNumber > compiledListSize) {
                argumentsList.add("...");
                break;
            }
        }

        return argumentsList.size() > 0 ? "(" + StringUtils.join(argumentsList, ", ") + ")" : "";
    }

    @Override
    public List<PerlSubArgument> getSubArgumentsList() {
        PerlSubDefinitionStub stub = getStub();
        if (stub != null)
            return stub.getSubArgumentsList();

        List<PerlSubArgument> arguments = new ArrayList<PerlSubArgument>();

        // todo add stubs reading here

        PsiPerlBlock subBlock = getBlock();

        if (subBlock.isValid()) {

            for (PsiElement statement : subBlock.getChildren()) {
                PsiPerlAssignExpr assignExpression = PsiTreeUtil.findChildOfType(statement,
                        PsiPerlAssignExpr.class);
                if (assignExpression != null) {
                    Collection<PsiPerlExpr> assignTerms = assignExpression.getExprList();
                    assert assignTerms instanceof SmartList;
                    if (assignTerms.size() == 2) {
                        // fixme need to implement things in assignExpr
                        PsiPerlExpr leftTerm = (PsiPerlExpr) ((SmartList) assignTerms).get(0);
                        PsiPerlExpr rightTerm = (PsiPerlExpr) ((SmartList) assignTerms).get(1);

                        if (leftTerm instanceof PsiPerlVariableDeclarationLexical) {
                            PsiPerlVariableDeclarationLexical declaration = (PsiPerlVariableDeclarationLexical) leftTerm;
                            PerlNamespaceElement variableClass = declaration.getNamespaceElement();
                            String definitionClassName = "";
                            if (variableClass != null)
                                definitionClassName = variableClass.getCanonicalName();

                            if ("@_".equals(rightTerm.getText())) {
                                for (PerlVariable variable : PsiTreeUtil.findChildrenOfType(declaration,
                                        PerlVariable.class)) {
                                    PerlVariableNameElement variableNameElement = variable.getVariableNameElement();

                                    if (variableNameElement != null)
                                        arguments.add(new PerlSubArgument(variable.getActualType(),
                                                variableNameElement.getName(), definitionClassName, true));
                                }
                                break;

                            } else if ("shift".equals(rightTerm.getText())) {
                                PerlVariable variable = PsiTreeUtil.findChildOfType(declaration,
                                        PerlVariable.class);

                                if (variable != null) {
                                    PerlVariableNameElement variableNameElement = variable.getVariableNameElement();

                                    if (variableNameElement != null)
                                        arguments.add(new PerlSubArgument(variable.getActualType(),
                                                variableNameElement.getName(), definitionClassName, true));
                                }
                            }
                        } else
                            // todo dunno what can else be here
                            break;
                    } else
                        // todo dunno how to handle this yet like my $scalar = my $something = shift;
                        break;
                } else
                    // not an assignment here
                    break;
            }
        }

        return arguments;
    }

    @Override
    public ItemPresentation getPresentation() {
        return new PerlItemPresentationSimple(this, getPresentableName());
    }

    @Override
    public String getPresentableName() {
        String args = getSubArgumentsListAsString();
        return this.getName() + (args.isEmpty() ? "()" : args);
    }

}