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
7 changes: 4 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ jobs:
- name: install fonts
run: sudo apt-get update -y && sudo apt-get install -y fonts-dejavu fontconfig
- name: setup java
uses: actions/setup-java@v1
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: temurin
java-version: '11'
- name: build asset
uses: eskatos/gradle-command-action@v2.0.1
uses: gradle/gradle-build-action@v2
with:
arguments: build
- name: fetch latest release
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ jobs:
- name: install fonts
run: sudo apt-get update -y && sudo apt-get install -y fonts-dejavu fontconfig
- name: setup java
uses: actions/setup-java@v1
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: temurin
java-version: '11'
- name: test plugin
uses: eskatos/gradle-command-action@v2.0.1
uses: gradle/gradle-build-action@v2
with:
arguments: :cleanTest :test check verifyPlugin
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Quick Mock
[![Build Status](https://travis-ci.com/cawolf/phpstorm-quick-mock.svg?branch=master)](https://travis-ci.com/cawolf/phpstorm-quick-mock)
[![Tests](https://github.com/cawolf/phpstorm-quick-mock/actions/workflows/test.yml/badge.svg)](https://github.com/cawolf/phpstorm-quick-mock/actions/workflows/test.yml)
[![Version](https://img.shields.io/jetbrains/plugin/v/11165?label=version)](https://plugins.jetbrains.com/plugin/11165-quick-mock)
[![Downloads](https://img.shields.io/jetbrains/plugin/d/11165)](https://plugins.jetbrains.com/plugin/11165-quick-mock)

Expand All @@ -13,7 +13,7 @@ Now, you can use this PHPStorm plugin to automatically generate mocks for these
constructor argument list, trigger code intentions (default: `ALT + ENTER`) and select `Quick Mock: add constructor prophecies` - done!

## Install
Install the plugin by going to `Settings -> Plugins -> Browse repositories` and then search for `Quick Mock`
Install the plugin by going to `Settings -> Plugins -> Marketplace` and then search for `Quick Mock`

## Options
You can configure the plugin under `Languages and Frameworks -> PHP -> Quick Mock`. Available options:
Expand Down
14 changes: 7 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent

plugins {
id 'java'
id 'org.jetbrains.intellij' version '0.7.3'
id 'org.jetbrains.intellij' version '1.3.0'
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.1'
id 'org.jetbrains.kotlin.jvm' version '1.6.10'
}
Expand Down Expand Up @@ -72,10 +72,10 @@ tasks.withType(Test) {
}

intellij {
type 'IU'
version ideaVersion
updateSinceUntilBuild false
plugins = [
type.set('IU')
version.set(ideaVersion)
updateSinceUntilBuild.set(false)
plugins.set([
"com.jetbrains.php:${phpPluginVersion}",
'coverage',
'webDeployment',
Expand All @@ -84,7 +84,7 @@ intellij {
'java-i18n',
'properties',
'xpath'
]
])

pluginName 'Quick Mock'
pluginName.set('Quick Mock')
}
14 changes: 7 additions & 7 deletions src/main/kotlin/de/cawolf/quickmock/intention/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ const val GENERATED_SUFFIX = "QuickMocked"

@JvmField
val PRIMITIVES = arrayOf(
"string",
"int",
"float",
"bool",
"array",
"", // mixed
"object"
"string",
"int",
"float",
"bool",
"array",
"", // mixed
"object"
)
45 changes: 33 additions & 12 deletions src/main/kotlin/de/cawolf/quickmock/intention/QuickMockCreator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,28 @@ class QuickMockCreator : PsiElementBaseIntentionAction(), IntentionAction {
val newExpression = PsiTreeUtil.getParentOfType(psiElement, NewExpression::class.java)
return newExpression is NewExpression
&& newExpression.let { constructor.get(it) } != null
&& constructorParameters.get(psiElement, project).count() != newExpression.parameterList!!.children.count()
&& constructorParameters.get(psiElement, project)
.count() != newExpression.parameterList!!.children.count()
}

@Throws(IncorrectOperationException::class)
override fun invoke(project: Project, editor: Editor, psiElement: PsiElement) {
// init and safeguards: do not proceed if the current edited test class is not parsing correctly
val namespace = PsiTreeUtil.getParentOfType(psiElement, PhpNamespace::class.java)
?: return
?: return
val clazz = PsiTreeUtil.getParentOfType(psiElement, PhpClass::class.java)
?: return
val beginningOfClass = PsiTreeUtil.getParentOfType(psiElement, PhpClass::class.java)?.children?.find { it -> it is ImplementsList }?.nextSibling?.nextSibling
?: return
?: return
val beginningOfClass = PsiTreeUtil.getParentOfType(
psiElement,
PhpClass::class.java
)?.children?.find { it -> it is ImplementsList }?.nextSibling?.nextSibling
?: return
val constructStatement = PsiTreeUtil.getParentOfType(psiElement, AssignmentExpression::class.java)
?: return
?: return
val newExpression = PsiTreeUtil.getParentOfType(psiElement, NewExpression::class.java)
?: return
?: return
val parameterList = newExpression.parameterList
?: return
?: return

// get helper services
val addArguments = ServiceManager.getService(project, AddArguments::class.java)
Expand All @@ -54,7 +58,8 @@ class QuickMockCreator : PsiElementBaseIntentionAction(), IntentionAction {
val removeSurroundingWhitespaces = ServiceManager.getService(project, RemoveSurroundingWhitespaces::class.java)
val constructorParameters = ServiceManager.getService(project, ConstructorParameters::class.java)
val addNewlineBefore = ServiceManager.getService(project, AddNewlineBefore::class.java)
val removeWhitespaceBeforeConstruct = ServiceManager.getService(project, RemoveWhitespaceBeforeConstruct::class.java)
val removeWhitespaceBeforeConstruct =
ServiceManager.getService(project, RemoveWhitespaceBeforeConstruct::class.java)
val existingMocks = ServiceManager.getService(project, ExistingMocks::class.java)
val settings = ServiceManager.getService(Settings::class.java)

Expand All @@ -73,10 +78,22 @@ class QuickMockCreator : PsiElementBaseIntentionAction(), IntentionAction {
if (parametersWithoutMocks.contains(parameter)) {
val parameterClassName = parameter.type.toString().removeSuffix("[]")
parameterName = determineParameterName(clazz, parameter)
nonPrimitiveMocked = addMissingUseStatements.invoke(project, namespace, parameterClassName, aliasedUseStatementList[parameterClassName]) || nonPrimitiveMocked
nonPrimitiveMocked = addMissingUseStatements.invoke(
project,
namespace,
parameterClassName,
aliasedUseStatementList[parameterClassName]
) || nonPrimitiveMocked
addMockAssignment.invoke(project, constructStatement, parameter, parameterName)

currentAnchor = addProperty.invoke(project, parameter, parameterName, currentAnchor, clazz, settings.addDocBlockForMembers)
currentAnchor = addProperty.invoke(
project,
parameter,
parameterName,
currentAnchor,
clazz,
settings.addDocBlockForMembers
)
}

parameterMapByName.add(Pair(parameterName, parameter))
Expand All @@ -93,6 +110,10 @@ class QuickMockCreator : PsiElementBaseIntentionAction(), IntentionAction {
}

private fun determineParameterName(clazz: PhpClass, parameter: Parameter): String {
return if (clazz.findOwnFieldByName(parameter.name, false) == null && clazz.findFieldByName(parameter.name, false) != null) parameter.name + GENERATED_SUFFIX else parameter.name
return if (clazz.findOwnFieldByName(parameter.name, false) == null && clazz.findFieldByName(
parameter.name,
false
) != null
) parameter.name + GENERATED_SUFFIX else parameter.name
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ class AddArguments {
}

private fun createDummyFile(p: Project, fileText: String): PsiFile =
PsiFileFactory.getInstance(p).createFileFromText("DUMMY__.${PhpFileType.INSTANCE.defaultExtension}", PhpFileType.INSTANCE, "<?php\n$fileText", System.currentTimeMillis(), false)
PsiFileFactory.getInstance(p).createFileFromText(
"DUMMY__.${PhpFileType.INSTANCE.defaultExtension}",
PhpFileType.INSTANCE,
"<?php\n$fileText",
System.currentTimeMillis(),
false
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ class AddMissingUseStatements {
if (PRIMITIVES.contains(foldDocBlockTypeHintedArray.invoke(fqcn))) return false

val scopeHolder = PhpCodeInsightUtil.findScopeForUseOperator(namespace)
if (scopeHolder != null && PhpCodeInsightUtil.findImportedName(scopeHolder, fqcn, PhpUseKeyword.CLASS) == null && PhpCodeInsightUtil.canImport(scopeHolder, fqcn, PhpUseKeyword.CLASS)) {
if (scopeHolder != null && PhpCodeInsightUtil.findImportedName(
scopeHolder,
fqcn,
PhpUseKeyword.CLASS
) == null && PhpCodeInsightUtil.canImport(scopeHolder, fqcn, PhpUseKeyword.CLASS)
) {
PhpAliasImporter.insertUseStatement(fqcn, alias, scopeHolder)
}
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class AddMockAssignment {
fun invoke(project: Project, constructStatement: PsiElement, parameter: Parameter, parameterName: String) {
val whitespaceType = IElementType.enumerate { it.toString() == "WHITE_SPACE" }.first()
val mockAssignment = PhpPsiElementFactory.createStatement(
project,
"\$this->$parameterName = ${mockValueFromType(parameter, project)};"
project,
"\$this->$parameterName = ${mockValueFromType(parameter, project)};"
)

val currentMethod = constructStatement.parent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import com.jetbrains.php.lang.psi.PhpPsiElementFactory
class AddNewlineBefore {
fun invoke(psiElement: PsiElement, project: Project) {
val currentMethod = psiElement.parent
currentMethod.addBefore(PhpPsiElementFactory.createFromText(project, PsiWhiteSpace::class.java, "\n")!!, psiElement)
currentMethod.addBefore(
PhpPsiElementFactory.createFromText(project, PsiWhiteSpace::class.java, "\n")!!,
psiElement
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,32 @@ import com.jetbrains.php.lang.psi.elements.PhpClass
import de.cawolf.quickmock.intention.PRIMITIVES

class AddProperty {
fun invoke(project: Project, parameter: Parameter, parameterName: String, currentAnchor: PsiElement, clazz: PhpClass, addDocBlockForMembers: Boolean): PsiElement {
fun invoke(
project: Project,
parameter: Parameter,
parameterName: String,
currentAnchor: PsiElement,
clazz: PhpClass,
addDocBlockForMembers: Boolean
): PsiElement {
val classFieldsType = IElementType.enumerate { it.toString() == "Class fields" }.first()
val docCommentType = IElementType.enumerate { it.toString() == "PhpDocComment" }.first()

val field = PhpPsiElementFactory.createFromText(project, classFieldsType, "class C { private \$$parameterName; }")
val field =
PhpPsiElementFactory.createFromText(project, classFieldsType, "class C { private \$$parameterName; }")
val fieldAnchor = clazz.addAfter(field, currentAnchor)

if (addDocBlockForMembers) {
val foldDocBlockTypeHintedArray = ServiceManager.getService(project, FoldDocBlockTypeHintedArray::class.java)
val foldDocBlockTypeHintedArray =
ServiceManager.getService(project, FoldDocBlockTypeHintedArray::class.java)

val foldedType = foldDocBlockTypeHintedArray.invoke(parameter.type.toString())
val objectProphecy = if (PRIMITIVES.contains(foldedType)) "" else "|ObjectProphecy"
val docBlock = PhpPsiElementFactory.createFromText(project, docCommentType, "/** @var ${determineTypeHint(parameter, foldedType)}$objectProphecy */\n\$foo = null;")
val docBlock = PhpPsiElementFactory.createFromText(
project,
docCommentType,
"/** @var ${determineTypeHint(parameter, foldedType)}$objectProphecy */\n\$foo = null;"
)
clazz.addBefore(docBlock, fieldAnchor)
}

Expand All @@ -33,7 +46,8 @@ class AddProperty {
return when {
foldedType == "" -> "mixed"
foldedType.contains('\\') -> when {
foldedType.split('\\').last() != parameter.node.firstChildNode.text -> parameter.node.firstChildNode.text
foldedType.split('\\')
.last() != parameter.node.firstChildNode.text -> parameter.node.firstChildNode.text
else -> foldedType.split('\\').last()
}
else -> foldedType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ class AliasedUseStatements {
val useLists = PhpCodeInsightUtil.collectImports(containingClass?.parent?.parent as PhpPsiElement)
for (useList in useLists) {
if (useList.declarations.size == 1) {
useList.declarations[0].aliasName?.let { aliasedUseStatements.put((useList.firstPsiChild?.firstPsiChild as ClassReferenceImpl).type.toString(), it) }
useList.declarations[0].aliasName.let {
if (it != null) {
aliasedUseStatements.put(
(useList.firstPsiChild!!.firstPsiChild as ClassReferenceImpl).type.toString(),
it
)
}
}
}
}
return aliasedUseStatements
Expand Down