Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
<fileBasedIndex implementation="com.magento.idea.magento2plugin.stubs.indexes.js.MagentoLibJsIndex" />
<fileBasedIndex implementation="com.magento.idea.magento2plugin.stubs.indexes.xml.AclResourceIndex" />
<fileBasedIndex implementation="com.magento.idea.magento2plugin.stubs.indexes.xml.MenuIndex" />
<fileBasedIndex implementation="com.magento.idea.magento2plugin.stubs.indexes.xml.UIComponentIndex" />

<codeInsight.lineMarkerProvider language="PHP" implementationClass="com.magento.idea.magento2plugin.linemarker.php.PluginLineMarkerProvider"/>
<codeInsight.lineMarkerProvider language="PHP" implementationClass="com.magento.idea.magento2plugin.linemarker.php.PluginTargetLineMarkerProvider"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.completion.provider;

import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ProcessingContext;
import com.jetbrains.php.PhpIcons;
import com.magento.idea.magento2plugin.indexes.UIComponentIndex;
import java.util.List;
import org.jetbrains.annotations.NotNull;


public class UiComponentCompletionProvider extends CompletionProvider<CompletionParameters> {

@Override
protected void addCompletions(@NotNull final CompletionParameters parameters,
final ProcessingContext context,
@NotNull final CompletionResultSet result) {
final PsiElement position = parameters.getPosition().getOriginalElement();
if (position == null) {
return;
}

final List<XmlFile> targets = UIComponentIndex.getUiComponentFiles(position.getProject());
if (!targets.isEmpty()) {
for (final XmlFile file : targets) {
result.addElement(LookupElementBuilder
.create(file.getVirtualFile().getNameWithoutExtension())
.withIcon(PhpIcons.XML_TAG_ICON)
);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ public XmlCompletionContributor() {
new FilePathCompletionProvider()
);

// <uiComponent name="completion"/>
extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN)
.inside(XmlPatterns.xmlAttribute().withName(LayoutXml.NAME_ATTRIBUTE)
.withParent(XmlPatterns.xmlTag().withName(LayoutXml.UI_COMPONENT_TAG_NAME))),
new UiComponentCompletionProvider()
);

extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_DATA_CHARACTERS)
.withParent(XmlPatterns.xmlText().withParent(
XmlPatterns.xmlTag().withName(UiComponentXml.XML_TAG_ITEM).withChild(
Expand Down Expand Up @@ -126,20 +133,20 @@ public XmlCompletionContributor() {

// <observer instance="Class">
extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN)
.inside(XmlPatterns.xmlAttribute().withName(ModuleEventsXml.INSTANCE_ATTRIBUTE)
.withParent(XmlPatterns.xmlTag().withName(ModuleEventsXml.OBSERVER_TAG)
)
).inFile(xmlFile().withName(string().matches(ModuleEventsXml.FILE_NAME))),
new PhpClassCompletionProvider()
.inside(XmlPatterns.xmlAttribute().withName(ModuleEventsXml.INSTANCE_ATTRIBUTE)
.withParent(XmlPatterns.xmlTag().withName(ModuleEventsXml.OBSERVER_TAG)
)
).inFile(xmlFile().withName(string().matches(ModuleEventsXml.FILE_NAME))),
new PhpClassCompletionProvider()
);

// <job instance="class">
extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN)
.inside(XmlPatterns.xmlAttribute().withName(CommonXml.ATTR_INSTANCE)
.withParent(XmlPatterns.xmlTag().withName(CrontabXmlTemplate.CRON_JOB_TAG)
)
).inFile(xmlFile().withName(string().matches(CrontabXmlTemplate.FILE_NAME))),
new PhpClassCompletionProvider()
.inside(XmlPatterns.xmlAttribute().withName(CommonXml.ATTR_INSTANCE)
.withParent(XmlPatterns.xmlTag().withName(CrontabXmlTemplate.CRON_JOB_TAG)
)
).inFile(xmlFile().withName(string().matches(CrontabXmlTemplate.FILE_NAME))),
new PhpClassCompletionProvider()
);

// <source_model>php class completion</source_model> in system.xml files.
Expand Down
136 changes: 136 additions & 0 deletions src/com/magento/idea/magento2plugin/indexes/UIComponentIndex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.indexes;

import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.ID;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jetbrains.annotations.Nullable;

@SuppressWarnings("PMD")
public final class UIComponentIndex {

private UIComponentIndex() {
throw new AssertionError("Instantiating utility class...");
}

/**
* Available ui component file.
*
* @param virtualFile VirtualFile
* @return boolean
*/
public static boolean isUiComponentFile(final VirtualFile virtualFile) {
final VirtualFile parent = virtualFile.getParent();
return virtualFile.getFileType() == XmlFileType.INSTANCE && parent.isDirectory()
&& parent.getName().endsWith("ui_component");
}

/**
* Get ui component files.
*
* @param project Project
* @param fileName String
* @return List
*/
public static List<XmlFile> getUiComponentFiles(
final Project project,
final @Nullable String fileName
) {
final List<XmlFile> results = new ArrayList<XmlFile>();//NOPMD
final Collection<VirtualFile> xmlFiles = FilenameIndex.getAllFilesByExt(project, "xml");

final PsiManager psiManager = PsiManager.getInstance(project);
for (final VirtualFile xmlFile: xmlFiles) {
if (isUiComponentFile(xmlFile)) {
if (fileName != null && !xmlFile.getNameWithoutExtension().equals(fileName)) {
continue;
}

final PsiFile file = psiManager.findFile(xmlFile);
if (file != null) {
results.add((XmlFile)file);
}
}
}

return results;
}

/**
* Get ui component files.
*
* @param project Project
* @return List
*/
public static List<XmlFile> getUiComponentFiles(final Project project) {
return getUiComponentFiles(project, null);
}

/**
* Get All Keys.
*
* @param identifier ID
* @param project Project
* @return Collection
*/
public static Collection<String> getAllKeys(
final ID<String, Void> identifier,
final Project project
) {
return FileBasedIndex.getInstance().getAllKeys(identifier, project);
}

/**
* Get ui component files.
*
* @param project Project
* @param fileName String
* @return List
*/
public static List<XmlFile> getUIComponentFiles(Project project, @Nullable String fileName) {
List<XmlFile> results = new ArrayList<XmlFile>();
Collection<VirtualFile> xmlFiles = FilenameIndex.getAllFilesByExt(project, "xml");

PsiManager psiManager = PsiManager.getInstance(project);
for (VirtualFile xmlFile: xmlFiles) {
if (isUIComponentFile(xmlFile)) {
if (fileName != null && !xmlFile.getNameWithoutExtension().equals(fileName)) {
continue;
}

PsiFile file = psiManager.findFile(xmlFile);
if (file != null) {
results.add((XmlFile)file);
}
}
}

return results;
}

/**
* Available ui component file.
*
* @param virtualFile VirtualFile
* @return boolean
*/
public static boolean isUIComponentFile(VirtualFile virtualFile) {
VirtualFile parent = virtualFile.getParent();
return virtualFile.getFileType() == XmlFileType.INSTANCE && parent.isDirectory()
&& parent.getName().endsWith("ui_component");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.reference.provider;

import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceProvider;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ProcessingContext;
import com.magento.idea.magento2plugin.indexes.UIComponentIndex;
import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase;
import java.util.List;
import org.jetbrains.annotations.NotNull;


public class UIComponentReferenceProvider extends PsiReferenceProvider {

@NotNull
@Override
public PsiReference[] getReferencesByElement(
@NotNull final PsiElement element,
@NotNull final ProcessingContext context
) {
final String value = StringUtil.unquoteString(element.getText());
final List<XmlFile> targets = UIComponentIndex.getUIComponentFiles(
element.getProject(),
value
);
if (!targets.isEmpty()) {
return new PsiReference[] {new PolyVariantReferenceBase(element, targets)};
}
return PsiReference.EMPTY_ARRAY;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar)
new LayoutUpdateReferenceProvider()
);

// <uiComponent name="completion"/>
registrar.registerReferenceProvider(
XmlPatterns.xmlAttributeValue().withParent(
XmlPatterns.xmlAttribute().withName("name").withParent(
XmlPatterns.xmlTag().withName("uiComponent")
)
),
new UIComponentReferenceProvider()
);

// <event name="reference" />
registrar.registerReferenceProvider(
XmlPatterns.xmlAttributeValue().withParent(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.stubs.indexes.xml;

import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.util.indexing.DataIndexer;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.FileContent;
import com.intellij.util.indexing.ID;
import com.intellij.util.indexing.ScalarIndexExtension;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.xml.impl.DomApplicationComponent;
import com.magento.idea.magento2plugin.project.Settings;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.NotNull;


public class UIComponentIndex extends ScalarIndexExtension<String> {

public static final ID<String, Void> KEY =
ID.create("com.magento.idea.magento2plugin.stubs.indexes.ui_component");

@NotNull
@Override
public ID<String, Void> getName() {
return KEY;
}

/**
* Indexer for `ui_component` files.
*
* @return this
*/
@NotNull
@Override
public DataIndexer<String, Void, FileContent> getIndexer() {
return inputData -> {
final Map<String, Void> map = new HashMap<>();//NOPMD

final PsiFile psiFile = inputData.getPsiFile();
if (!Settings.isEnabled(psiFile.getProject())) {
return map;
}

final VirtualFile file = inputData.getFile();
if (!file.getPath().matches("uiComponent")) {
return map;
}

final String key = file.getName();
if (!key.isEmpty()) {
map.put(key, null);
}

return map;
};
}

@NotNull
@Override
public KeyDescriptor<String> getKeyDescriptor() {
return new EnumeratorStringDescriptor();
}

@NotNull
@Override
public FileBasedIndex.InputFilter getInputFilter() {
return file -> file.getFileType() == XmlFileType.INSTANCE;
}

@Override
public boolean dependsOnFileContent() {
return true;
}

@Override
public int getVersion() {
return DomApplicationComponent.getInstance().getCumulativeVersion(false);
}
}