Skip to content

Commit

Permalink
Merge pull request #34 from nvlad/feature/components
Browse files Browse the repository at this point in the history
Feature/components
  • Loading branch information
nvlad authored Mar 15, 2017
2 parents 58ea477 + a53ce62 commit 799c881
Show file tree
Hide file tree
Showing 18 changed files with 958 additions and 4 deletions.
12 changes: 11 additions & 1 deletion resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<idea-plugin version="2">
<id>com.yii2support</id>
<name>Yii2 Support</name>
<version>0.2.10.11</version>
<version>0.3.10.11</version>
<vendor email="[email protected]" url="http://nvlad.com">NVlad</vendor>

<description><![CDATA[
Expand Down Expand Up @@ -46,8 +46,15 @@
<extensions defaultExtensionNs="com.intellij">
<!-- Views -->
<completion.contributor language="PHP" implementationClass="com.nvlad.yii2support.views.completion.CompletionContributor"/>
<completion.contributor language="PHP" implementationClass="com.nvlad.yii2support.objectfactory.ObjectFactoryCompletionContributor"/>
<psi.referenceContributor language="PHP" implementation="com.nvlad.yii2support.views.references.PsiReferenceContributor"/>
<psi.referenceContributor language="PHP" implementation="com.nvlad.yii2support.objectfactory.ObjectFactoryReferenceContributor"/>
<renamePsiElementProcessor implementation="com.nvlad.yii2support.views.refactor.RenameViewProcessor"/>
<localInspection language="PHP" shortName="MissedFieldInspection"
displayName="Missing Field file"
groupName="Views" groupPath="PHP,Framework,Yii2"
enabledByDefault="true" level="ERROR"
implementationClass="com.nvlad.yii2support.objectfactory.ObjectFactoryMissedFieldInspection"/>
<localInspection language="PHP" shortName="MissedViewInspection"
displayName="Missing View file"
groupName="Views" groupPath="PHP,Framework,Yii2"
Expand All @@ -66,6 +73,9 @@

<!-- i18n -->
<completion.contributor language="PHP" implementationClass="com.nvlad.yii2support.i18n.CompletionContributor"/>

<!-- Component -->
<completion.contributor language="PHP" implementationClass="com.nvlad.yii2support.components.ComponentConfigCompletionContributor"/>
</extensions>

<actions>
Expand Down
12 changes: 11 additions & 1 deletion src/com/nvlad/yii2support/common/Patterns.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.intellij.util.ProcessingContext;
import com.jetbrains.php.injection.PhpElementPattern.Capture;
import com.jetbrains.php.lang.psi.elements.MethodReference;
import com.jetbrains.php.lang.psi.elements.PhpPsiElement;
import org.jetbrains.annotations.Nullable;

/**
Expand All @@ -24,4 +25,13 @@ public boolean accepts(@Nullable Object o, ProcessingContext context) {
}
});
}
}

public static Capture<PhpPsiElement> withHashKey() {
return new Capture<>(new InitialPatternCondition<PhpPsiElement>(PhpPsiElement.class) {
@Override
public boolean accepts(@Nullable Object o, ProcessingContext context) {
return o != null && o.toString().equals("Array key");
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.nvlad.yii2support.components;

import com.intellij.codeInsight.completion.CompletionContributor;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement;
import com.jetbrains.php.lang.psi.elements.ArrayCreationExpression;
import com.jetbrains.php.lang.psi.elements.NewExpression;
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
import com.nvlad.yii2support.common.Patterns;
import org.jetbrains.annotations.NotNull;

/**
* Created by NVlad on 11.01.2017.
*/
public class ComponentConfigCompletionContributor extends CompletionContributor {
public ComponentConfigCompletionContributor() {
extend(CompletionType.BASIC, ElementPattern(), new ComponentConfigCompletionProvider());
}

@Override
public boolean invokeAutoPopup(@NotNull PsiElement position, char typeChar) {
if ((typeChar == '\'' || typeChar == '"') && position.getParent() instanceof ArrayCreationExpression) {
return true;
}

return false;
}

private static ElementPattern<PsiElement> ElementPattern() {
//noinspection unchecked
return PlatformPatterns.psiElement()
.withParent(PlatformPatterns.psiElement(StringLiteralExpression.class)
.withParent(PlatformPatterns.or(
PlatformPatterns.psiElement().withSuperParent(3, NewExpression.class),
Patterns.withHashKey()
.withParent(PlatformPatterns.psiElement().withSuperParent(3, NewExpression.class))
)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.nvlad.yii2support.components;

import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.util.ProcessingContext;
import com.jetbrains.php.lang.psi.elements.*;
import org.jetbrains.annotations.NotNull;

/**
* Created by NVlad on 11.01.2017.
*/
public class ComponentConfigCompletionProvider extends CompletionProvider<CompletionParameters> {
@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) {
PhpExpression element = (PhpExpression) completionParameters.getPosition().getParent();

NewExpression newExpression = ComponentUtil.configForNewExpression(element);
if (newExpression != null) {
PhpClass phpClass = ComponentUtil.getPhpClass(newExpression);
if (phpClass != null) {
Method constructor = phpClass.getConstructor();
ParameterList parameterList = newExpression.getParameterList();
if (constructor != null && parameterList != null) {
int paramIndex = ComponentUtil.paramIndexForElement(element);

if (paramIndex != -1) {
Parameter[] parameters = constructor.getParameters();

if (paramIndex < parameters.length && parameters[paramIndex].getName().equals("config")) {
for (Field field : ComponentUtil.getClassFields(phpClass)) {
completionResultSet.addElement(new ComponentFieldLookupElement(element, field));
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.nvlad.yii2support.components;

import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.openapi.editor.Document;
import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment;
import com.jetbrains.php.lang.documentation.phpdoc.psi.tags.PhpDocParamTag;
import com.jetbrains.php.lang.psi.elements.ArrayCreationExpression;
import com.jetbrains.php.lang.psi.elements.ConstantReference;
import com.jetbrains.php.lang.psi.elements.Field;
import com.jetbrains.php.lang.psi.elements.PhpExpression;
import org.jetbrains.annotations.NotNull;

/**
* Created by NVlad on 11.01.2017.
*/
public class ComponentFieldLookupElement extends LookupElement {
private PhpExpression myElement;
private Field myField;

ComponentFieldLookupElement(PhpExpression element, Field field) {
myElement = element;
myField = field;
}

@NotNull
@Override
public String getLookupString() {
if (myElement instanceof ConstantReference) {
return "'" + myField.getName() + "'";
}

return myField.getName();
}

@Override
public void renderElement(LookupElementPresentation presentation) {
presentation.setIcon(myField.getIcon());
presentation.setItemText(myField.getName());
presentation.setItemTextBold(true);

presentation.setTypeText(myField.getType().toString());
presentation.setTypeGrayed(true);

PhpDocComment docComment = myField.getDocComment();
if (docComment != null) {
PhpDocParamTag paramTag = docComment.getVarTag();
if (paramTag != null) {
presentation.setTailText(" " + paramTag.getTagValue(), true);
}
}

}

@Override
public void handleInsert(InsertionContext context) {
super.handleInsert(context);

Document document = context.getDocument();
int insertPosition = context.getSelectionEndOffset();

if (myElement.getParent().getParent() instanceof ArrayCreationExpression) {
document.insertString(insertPosition + 1, " => ");
insertPosition += 5;

context.getEditor().getCaretModel().getCurrentCaret().moveToOffset(insertPosition);
}
}
}
110 changes: 110 additions & 0 deletions src/com/nvlad/yii2support/components/ComponentUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.nvlad.yii2support.components;

import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocProperty;
import com.jetbrains.php.lang.psi.elements.*;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.HashSet;

/**
* Created by NVlad on 11.01.2017.
*/
class ComponentUtil {
@Nullable
static NewExpression configForNewExpression(PsiElement psiElement) {
if (psiElement instanceof NewExpression) {
return (NewExpression) psiElement;
}

PsiElement parent = psiElement.getParent();
if (parent != null) {
return configForNewExpression(parent);
}

return null;
}

static int paramIndexForElement(PsiElement psiElement) {
PsiElement parent = psiElement.getParent();
if (parent == null) {
return -1;
}

if (parent instanceof ParameterList) {
return ArrayUtil.indexOf(((ParameterList) parent).getParameters(), psiElement);
}

return paramIndexForElement(parent);
}


@Nullable
static PhpClass getPhpClass(PhpPsiElement phpPsiElement) {
while (phpPsiElement != null) {
if (phpPsiElement instanceof ClassReference) {
return (PhpClass) ((ClassReference) phpPsiElement).resolve();
}
if (phpPsiElement instanceof NewExpression) {
ClassReference classReference = ((NewExpression) phpPsiElement).getClassReference();
if (classReference != null) {
PhpPsiElement resolve = (PhpPsiElement) classReference.resolve();
if (resolve instanceof PhpClass) {
return (PhpClass) resolve;
}
}
}

phpPsiElement = (PhpPsiElement) phpPsiElement.getParent();
}

return null;
}

static Collection<Field> getClassFields(PhpClass phpClass) {
final HashSet<Field> result = new HashSet<>();

final Collection<Field> fields = phpClass.getFields();
final Collection<Method> methods = phpClass.getMethods();
for (Field field : fields) {
if (field.isConstant()) {
continue;
}

final PhpModifier modifier = field.getModifier();
if (!modifier.isPublic() || modifier.isStatic()) {
continue;
}

if (field instanceof PhpDocProperty) {
final String setter = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Boolean setterExist = false;
for (Method method : methods) {
if (method.getName().equals(setter)) {
setterExist = true;
break;
}
}
if (!setterExist) {
String getter = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Boolean getterExist = false;
for (Method method : methods) {
if (method.getName().equals(getter)) {
getterExist = true;
break;
}
}
if (getterExist) {
continue;
}
}
}

result.add(field);
}

return result;
}
}
Loading

0 comments on commit 799c881

Please sign in to comment.