Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
olivernybroe committed Oct 22, 2020
1 parent 1d8f788 commit cac519e
Show file tree
Hide file tree
Showing 21 changed files with 289 additions and 63 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: olivernybroe
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
## [Unreleased]
### Added
- Initial scaffold created from [IntelliJ Platform Plugin Template](https://github.com/JetBrains/intellij-platform-plugin-template)
- Added foreach to collection refactoring
45 changes: 24 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
# collections-intellij

![Build](https://github.com/olivernybroe/collections-intellij/workflows/Build/badge.svg)
[![Version](https://img.shields.io/jetbrains/plugin/v/PLUGIN_ID.svg)](https://plugins.jetbrains.com/plugin/PLUGIN_ID)
[![Downloads](https://img.shields.io/jetbrains/plugin/d/PLUGIN_ID.svg)](https://plugins.jetbrains.com/plugin/PLUGIN_ID)

## Template ToDo list
- [x] Create a new [IntelliJ Platform Plugin Template][template] project.
- [ ] Verify the [pluginGroup](/gradle.properties), [plugin ID](/src/main/resources/META-INF/plugin.xml) and [sources package](/src/main/kotlin).
- [ ] Review the [Legal Agreements](https://plugins.jetbrains.com/docs/marketplace/legal-agreements.html).
- [ ] [Publish a plugin manually](https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/publishing_plugin.html) for the first time.
- [ ] Set the Plugin ID in the above README badges.
- [ ] Set the [Deployment Token](https://plugins.jetbrains.com/docs/marketplace/plugin-upload.html).
- [ ] Click the <kbd>Watch</kbd> button on the top of the [IntelliJ Platform Plugin Template][template] to be notified about releases containing new features and fixes.
<p align="center">
<img src="/art/banner.png" width="914" title="Collector Banner">
<p align="center">
<a href="https://github.com/olivernybroe/collections-intellij/workflows"><img alt="GitHub Workflow Status (master)" src="https://github.com/olivernybroe/collections-intellij/workflows/Build/badge.svg"></a>
<a href="https://plugins.jetbrains.com/plugin/15246"><img alt="Total Downloads" src="https://img.shields.io/jetbrains/plugin/d/15246"></a>
<a href="https://plugins.jetbrains.com/plugin/15246"><img alt="Latest Version" src="https://img.shields.io/jetbrains/plugin/v/15246"></a>
<a href="https://plugins.jetbrains.com/plugin/15246"><img alt="Latest EAP Version" src="https://img.shields.io/badge/dynamic/xml?label=EAP version&query=%2Fplugin-repository%2Fcategory%2Fidea-plugin%5B1%5D%2Fversion&url=https%3A%2F%2Fplugins.jetbrains.com%2Fplugins%2Flist%3Fchannel%3Deap%26pluginId%3D15246"></a>
</p>
</p>

# Collector - A collection's plugin for PhpStorm

<!-- Plugin description -->
This Fancy IntelliJ Platform Plugin is going to be your implementation of the brilliant ideas that you have.
This plugin adds support for Laravel Collections.

This specific section is a source for the [plugin.xml](/src/main/resources/META-INF/plugin.xml) file which will be extracted by the [Gradle](/build.gradle.kts) during the build process.

To keep everything working, do not remove `<!-- ... -->` sections.
It contains a bunch of handy refactorings for making your collections better.
It can also convert normal PHP statements into collections.
<!-- Plugin description end -->

## Installation

- Using IDE built-in plugin system:
<kbd>Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>Marketplace</kbd> > <kbd>Search for "collections-intellij"</kbd> >

<kbd>Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>Marketplace</kbd> > <kbd>Search for "Collector"</kbd> >
<kbd>Install Plugin</kbd>

- Manually:

Download the [latest release](https://github.com/olivernybroe/collections-intellij/releases/latest) and install it manually using
<kbd>Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>

- Using Early Access Program (EAP) builds:

<kbd>Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Manage plugin repositories</kbd>

Add a new entry for [`https://plugins.jetbrains.com/plugins/eap/15246`](https://plugins.jetbrains.com/plugins/eap/15246)

Then search for the plugin and install it as usual.

---
Plugin based on the [IntelliJ Platform Plugin Template][template].
Expand Down
17 changes: 8 additions & 9 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
# IntelliJ Platform Artifacts Repositories
# -> https://www.jetbrains.org/intellij/sdk/docs/reference_guide/intellij_artifacts.html

pluginGroup = com.github.olivernybroe.collectionsintellij
pluginName_ = collections-intellij
pluginVersion = 0.0.1
pluginGroup = dev.nybroe.collector
pluginName_ = Collector
pluginVersion = 0.0.1-EAP.1
pluginSinceBuild = 193
pluginUntilBuild = 202.*
pluginUntilBuild =

platformType = IC
platformVersion = 2019.3
platformType = IU
platformVersion = 2020.2.3
platformDownloadSources = true
# Plugin Dependencies -> https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_dependencies.html
# Example: platformPlugins = com.intellij.java,com.jetbrains.php:203.4449.22
platformPlugins =
# Get latest version from https://plugins.jetbrains.com/plugin/6610-php/versions
platformPlugins = com.jetbrains.php:202.7660.42

# Opt-out flag for bundling Kotlin standard library.
# See https://kotlinlang.org/docs/reference/using-gradle.html#dependency-on-the-standard-library for details.
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.github.olivernybroe.collectionsintellij
package dev.nybroe.collector

import com.intellij.AbstractBundle
import org.jetbrains.annotations.NonNls
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.nybroe.collector.inspections

import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import com.jetbrains.php.lang.inspections.PhpInspection
import com.jetbrains.php.lang.psi.elements.ForeachStatement
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor
import dev.nybroe.collector.MyBundle
import dev.nybroe.collector.quickFixes.ForeachToCollectionQuickFix

class ForeachToCollectionInspection : PhpInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : PhpElementVisitor() {
override fun visitPhpForeach(foreach: ForeachStatement) {
holder.registerProblem(
foreach,
MyBundle.message("foreachToCollectionDescription"),
ProblemHighlightType.INFORMATION,
ForeachToCollectionQuickFix()
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.github.olivernybroe.collectionsintellij.listeners
package dev.nybroe.collector.listeners

import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManagerListener
import com.github.olivernybroe.collectionsintellij.services.MyProjectService
import dev.nybroe.collector.services.MyProjectService

internal class MyProjectManagerListener : ProjectManagerListener {

override fun projectOpened(project: Project) {
project.getService(MyProjectService::class.java)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package dev.nybroe.collector.quickFixes

import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.util.PsiTreeUtil
import com.jetbrains.php.lang.inspections.codeStyle.PhpLoopCanBeConvertedToArrayMapInspection
import com.jetbrains.php.lang.psi.PhpPsiElementFactory
import com.jetbrains.php.lang.psi.elements.ForeachStatement
import com.jetbrains.php.lang.psi.elements.ParameterList
import com.jetbrains.php.lang.psi.elements.PhpNamedElement
import com.jetbrains.php.lang.psi.elements.Variable

class ForeachToCollectionQuickFix : LocalQuickFix {
companion object {
const val QUICK_FIX_NAME = "Refactor foreach to collection"
}

override fun getFamilyName(): String {
return QUICK_FIX_NAME
}

override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val foreach = descriptor.psiElement

if (foreach !is ForeachStatement) {
return
}

val statement = PhpLoopCanBeConvertedToArrayMapInspection.unwrapStatement(foreach.statement)!!

val arguments = createArguments(project, foreach)

val useList = createUseListStatement(
foreach,
arrayOf(
foreach.key?.name,
foreach.value?.name,
if (foreach.array is PhpNamedElement) (foreach.array as PhpNamedElement).name else null
).asSequence().filterNotNull().toList()
) ?: ""

val psiCollectionCall = PhpPsiElementFactory.createStatement(
project,
"collect(${foreach.array!!.text})->each(function(${arguments.text}) $useList {${statement.text}});"
)

descriptor.psiElement.replace(
psiCollectionCall
)
}

private fun createArguments(project: Project, foreach: ForeachStatement): ParameterList {
return PhpPsiElementFactory.createArgumentList(
project,
foreach.value!!.text
+ if (foreach.key != null) ", ${foreach.key!!.text}" else ""
)
}

private fun createUseListStatement(foreach: ForeachStatement, ignoredNames: List<String>): String? {
return PsiTreeUtil.collectElementsOfType(foreach, Variable::class.java)
.map { it.name }
.filter { !ignoredNames.contains(it) }
.ifEmpty { return null }
.joinToString(separator = ", ") { "$$it" }
.let { "use ($it)" }
}
}
10 changes: 10 additions & 0 deletions src/main/kotlin/dev/nybroe/collector/services/MyProjectService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package dev.nybroe.collector.services

import com.intellij.openapi.project.Project
import dev.nybroe.collector.MyBundle

class MyProjectService(project: Project) {

init {
}
}
22 changes: 16 additions & 6 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
<idea-plugin>
<id>com.github.olivernybroe.collectionsintellij</id>
<name>collections-intellij</name>
<vendor>olivernybroe</vendor>
<id>dev.nybroe.collector</id>
<name>Collector</name>
<vendor email="[email protected]" url="https://nybroe.dev">Oliver Nybroe</vendor>

<!-- Product and plugin compatibility requirements -->
<!-- https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html -->
<depends>com.intellij.modules.platform</depends>
<depends>com.jetbrains.php</depends>

<extensions defaultExtensionNs="com.intellij">
<applicationService serviceImplementation="com.github.olivernybroe.collectionsintellij.services.MyApplicationService"/>
<projectService serviceImplementation="com.github.olivernybroe.collectionsintellij.services.MyProjectService"/>
<projectService serviceImplementation="dev.nybroe.collector.services.MyProjectService"/>
<localInspection
language="PHP"
groupPath="PHP"
groupKey="collectionGroupName"
shortName="ForeachToCollectionInspection"
enabledByDefault="true"
bundle="messages.MyBundle"
key="foreachToCollectionDisplayName"
implementationClass="dev.nybroe.collector.inspections.ForeachToCollectionInspection"
/>
</extensions>

<applicationListeners>
<listener class="com.github.olivernybroe.collectionsintellij.listeners.MyProjectManagerListener"
<listener class="dev.nybroe.collector.listeners.MyProjectManagerListener"
topic="com.intellij.openapi.project.ProjectManagerListener"/>
</applicationListeners>
</idea-plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

<html lang="en">
<body>
'foreach' used instead of 'Collection'
</body>
</html>
8 changes: 6 additions & 2 deletions src/main/resources/messages/MyBundle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
name=My Plugin
applicationService=Application service
name=Collector
projectService=Project service: {0}

collectionGroupName=Collections

foreachToCollectionDisplayName='foreach' used instead of 'Collection'
foreachToCollectionDescription='foreach' used instead of 'Collection'
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dev.nybroe.collector.inspections

import com.intellij.testFramework.fixtures.BasePlatformTestCase
import dev.nybroe.collector.quickFixes.ForeachToCollectionQuickFix
import junit.framework.TestCase


internal class ForeachStatementInspectionTest : BasePlatformTestCase() {
override fun getTestDataPath(): String {
return "src/test/resources/inspections/ForeachStatementInspection"
}

/**
* Given the name of a test file, runs comparing references inspection quick fix and tests
* the results against a reference outcome file. File name pattern 'foo.java' and 'foo.after.java'
* are matching before and after files in the testData directory.
*
* @param testName The name of the test file before comparing references inspection.
*/
private fun doTest(testName: String) {
// Initialize the test based on the testData file
myFixture.configureByFile("$testName.php")
// Initialize the inspection and get a list of highlighted
myFixture.enableInspections(ForeachToCollectionInspection())
val highlightInfos = myFixture.doHighlighting()
TestCase.assertFalse(highlightInfos.isEmpty())
// Get the quick fix action for comparing references inspection and apply it to the file
val action = myFixture.findSingleIntention(ForeachToCollectionQuickFix.QUICK_FIX_NAME)
TestCase.assertNotNull(action)
myFixture.launchAction(action)
// Verify the results
myFixture.checkResultByFile("$testName.after.php")
}

fun testForeachValueOnly() {
doTest("foreach-value-only")
}

fun testForeachKeyValue() {
doTest("foreach-key-value")
}

fun testForeachOuterScopeVariable() {
doTest("foreach-outer-scope-variable")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

$array = [
'one' => 'monkey',
'two' => 'cow',
'tree' => 'snake',
];

collect($array)->each(function ($animal, $num) {
echo "{$num} = {$animal}";
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

$array = [
'one' => 'monkey',
'two' => 'cow',
'tree' => 'snake',
];

<caret>foreach ($array as $num => $animal) {
echo "{$num} = {$animal}";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

$array = [
'one',
'two',
'tree'
];

$name = 'one';

collect($array)->each(function ($item) use ($name) {
if ($item === $name) {
echo "found it!";
}
});
Loading

0 comments on commit cac519e

Please sign in to comment.