-
Notifications
You must be signed in to change notification settings - Fork 5
introduce an intention to add @kphp-immutable-class annotation
#67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
ab86341
Introduced the AddImmutableClassAnnotationIntention
vldF f19903a
Added missing trailing empty lines
vldF abd478f
Add some local mutability analysis to hide the intention when class i…
vldF 3df73b9
Add missing <caret>
vldF 2da4b8c
Add <i></i> to the new intention description
vldF 40f74b6
code style fixes
vldF e066ed8
fix immutable_class_intention-7
vldF 8198639
add extra tests
vldF 5b21d95
add review issue with lhs
vldF dacb768
do not show the intention on interfaces and abstract classes
vldF 60c53c6
disable the intention on traits and anon classes
vldF File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
src/main/kotlin/com/vk/kphpstorm/intentions/AddImmutableClassAnnotationIntention.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| package com.vk.kphpstorm.intentions | ||
|
|
||
| import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction | ||
| import com.intellij.openapi.editor.Editor | ||
| import com.intellij.openapi.project.Project | ||
| import com.intellij.psi.PsiElement | ||
| import com.intellij.psi.search.LocalSearchScope | ||
| import com.intellij.psi.search.searches.ReferencesSearch | ||
| import com.intellij.psi.util.findParentInFile | ||
| import com.jetbrains.php.lang.psi.elements.AssignmentExpression | ||
| import com.jetbrains.php.lang.psi.elements.PhpClass | ||
| import com.vk.kphpstorm.inspections.helpers.PhpDocPsiBuilder | ||
| import com.vk.kphpstorm.kphptags.KphpImmutableClassDocTag | ||
|
|
||
| class AddImmutableClassAnnotationIntention : PsiElementBaseIntentionAction() { | ||
| override fun getText(): String = "Add @kphp-immutable-class" | ||
| override fun getFamilyName(): String = getText() | ||
|
|
||
| override fun isAvailable(project: Project, editor: Editor?, element: PsiElement): Boolean { | ||
| if (!element.isClassNameNode()) { | ||
| return false | ||
| } | ||
|
|
||
| val klass = element.parent as PhpClass | ||
| if (klass.isAbstract || klass.isInterface || klass.isTrait || klass.isAnonymous) { | ||
| return false | ||
| } | ||
|
|
||
| val klassDocNode = klass.docComment | ||
|
|
||
| // do not suggest if already present | ||
| if (klassDocNode != null && KphpImmutableClassDocTag.existsInDocComment(klassDocNode)) { | ||
| return false | ||
| } | ||
|
|
||
| return !isClassLocallyImmutable(klass) | ||
| } | ||
|
|
||
| /** | ||
| * Simple local class mutability check. If there is any field mutation in class, | ||
| * the class is mutable. The only exception is the class constructor | ||
| */ | ||
| private fun isClassLocallyImmutable(klass: PhpClass): Boolean { | ||
| val searchScope = LocalSearchScope(klass) | ||
| for (field in klass.fields) { | ||
| val hasAnyMutation = ReferencesSearch.search(field, searchScope).any { ref -> | ||
| val element = ref.element | ||
|
|
||
| isMutatingOp(element) && !isInClassConstructor(klass, element) | ||
| } | ||
|
|
||
| if (hasAnyMutation) { | ||
| return true | ||
| } | ||
| } | ||
|
|
||
| return false | ||
| } | ||
|
|
||
| private fun isMutatingOp(psiElement: PsiElement): Boolean { | ||
| val parent = psiElement.parent | ||
|
|
||
| return parent is AssignmentExpression && parent.variable == psiElement | ||
| } | ||
|
|
||
| private fun isInClassConstructor(klass: PhpClass, psiElement: PsiElement): Boolean { | ||
| val classConstructor = klass.constructor | ||
| return classConstructor != null && psiElement.findParentInFile { e -> e == classConstructor } != null | ||
| } | ||
|
|
||
| override fun invoke(project: Project, editor: Editor?, element: PsiElement) { | ||
| val klass = element.parent as PhpClass | ||
| PhpDocPsiBuilder.addTagToClass(klass, KphpImmutableClassDocTag) | ||
| } | ||
|
|
||
| private fun PsiElement.isClassNameNode(): Boolean { | ||
| val klass = this.parent as? PhpClass ?: return false | ||
| return klass.nameIdentifier == this | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
...n/resources/intentionDescriptions/AddImmutableClassAnnotationIntention/after.php.template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /** | ||
| * My favorite class | ||
| * <spot>@kphp-immutable-class</spot> | ||
| */ | ||
| class MyClass { | ||
| // ... | ||
| } |
6 changes: 6 additions & 0 deletions
6
.../resources/intentionDescriptions/AddImmutableClassAnnotationIntention/before.php.template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| /** | ||
| * My favorite class | ||
| */ | ||
| class MyClass { | ||
| // ... | ||
| } |
1 change: 1 addition & 0 deletions
1
...ain/resources/intentionDescriptions/AddImmutableClassAnnotationIntention/description.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Add <i>@kphp-immutable-class annotation</i> to the class |
5 changes: 5 additions & 0 deletions
5
src/test/fixtures/kphp_intentions/immutable_class_intention-1.fixture.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| <?php | ||
|
|
||
| class <caret>C1 { | ||
| // ... | ||
| } |
8 changes: 8 additions & 0 deletions
8
src/test/fixtures/kphp_intentions/immutable_class_intention-1.qf.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-immutable-class | ||
| */ | ||
| class C1 { | ||
| // ... | ||
| } |
7 changes: 7 additions & 0 deletions
7
src/test/fixtures/kphp_intentions/immutable_class_intention-10.fixture.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-serializable | ||
| * @kphp-color slow-ignore | ||
| */ | ||
| class <caret>C1 { } |
8 changes: 8 additions & 0 deletions
8
src/test/fixtures/kphp_intentions/immutable_class_intention-10.qf.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-immutable-class | ||
| * @kphp-serializable | ||
| * @kphp-color slow-ignore | ||
| */ | ||
| class <caret>C1 { } |
3 changes: 3 additions & 0 deletions
3
src/test/fixtures/kphp_intentions/immutable_class_intention-11.nointent.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| <?php | ||
|
|
||
| abstract class <caret>C1 { } |
3 changes: 3 additions & 0 deletions
3
src/test/fixtures/kphp_intentions/immutable_class_intention-12.nointent.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| <?php | ||
|
|
||
| interface <caret>C1 { } |
3 changes: 3 additions & 0 deletions
3
src/test/fixtures/kphp_intentions/immutable_class_intention-13.nointent.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| <?php | ||
|
|
||
| trait <caret>C1 { } |
8 changes: 8 additions & 0 deletions
8
src/test/fixtures/kphp_intentions/immutable_class_intention-2.nointention.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-immutable-class | ||
| */ | ||
| class <caret>C1 { | ||
| // ... | ||
| } |
7 changes: 7 additions & 0 deletions
7
src/test/fixtures/kphp_intentions/immutable_class_intention-3.nointention.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <?php | ||
|
|
||
| class C1 extends <caret>C2 { | ||
| // ... | ||
| } | ||
|
|
||
| class C2 {} |
6 changes: 6 additions & 0 deletions
6
src/test/fixtures/kphp_intentions/immutable_class_intention-4.nointention.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| <?php | ||
|
|
||
| class C1 { | ||
| <caret> | ||
| // ... | ||
| } |
9 changes: 9 additions & 0 deletions
9
src/test/fixtures/kphp_intentions/immutable_class_intention-5.nointention.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <?php | ||
|
|
||
| class <caret>C1 { | ||
| public int $field; | ||
|
|
||
| public function foo() { | ||
| $this->field = 1; // mutate the field | ||
| } | ||
| } |
10 changes: 10 additions & 0 deletions
10
src/test/fixtures/kphp_intentions/immutable_class_intention-6.fixture.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <?php | ||
|
|
||
| class <caret>C1 { | ||
| public int $field; | ||
|
|
||
| public function __construct(int $arg) | ||
| { | ||
| $this->field = $arg; // field mutation in constructor, that's ok | ||
| } | ||
| } |
13 changes: 13 additions & 0 deletions
13
src/test/fixtures/kphp_intentions/immutable_class_intention-6.qf.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-immutable-class | ||
| */ | ||
| class <caret>C1 { | ||
| public int $field; | ||
|
|
||
| public function __construct(int $arg) | ||
| { | ||
| $this->field = $arg; // field mutation in constructor, that's ok | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
src/test/fixtures/kphp_intentions/immutable_class_intention-7.fixture.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <?php | ||
|
|
||
| class <caret>C1 { | ||
| public int $field; | ||
| } | ||
|
|
||
| function foo() | ||
| { | ||
| $v = new C1(); | ||
| $v->field = 1; // mutation outside of a class, that's ok | ||
| } |
14 changes: 14 additions & 0 deletions
14
src/test/fixtures/kphp_intentions/immutable_class_intention-7.qf.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-immutable-class | ||
| */ | ||
| class <caret>C1 { | ||
| public int $field; | ||
| } | ||
|
|
||
| function foo() | ||
| { | ||
| $v = new C1(); | ||
| $v->field = 1; // mutation outside of a class, that's ok | ||
| } |
9 changes: 9 additions & 0 deletions
9
src/test/fixtures/kphp_intentions/immutable_class_intention-8.fixture.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <?php | ||
|
|
||
| class <caret>C1 { | ||
| public int $field = 1; | ||
|
|
||
| public function foo() { | ||
| $tmp = $this->field; // no field mutation | ||
| } | ||
| } |
12 changes: 12 additions & 0 deletions
12
src/test/fixtures/kphp_intentions/immutable_class_intention-8.qf.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-immutable-class | ||
| */ | ||
| class <caret>C1 { | ||
| public int $field = 1; | ||
|
|
||
| public function foo() { | ||
| $tmp = $this->field; // no field mutation | ||
| } | ||
| } |
4 changes: 4 additions & 0 deletions
4
src/test/fixtures/kphp_intentions/immutable_class_intention-9.fixture.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| <?php | ||
|
|
||
| /** @kphp-serializable */ | ||
| class <caret>C1 { } |
7 changes: 7 additions & 0 deletions
7
src/test/fixtures/kphp_intentions/immutable_class_intention-9.qf.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * @kphp-immutable-class | ||
| * @kphp-serializable | ||
| */ | ||
| class <caret>C1 { } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
src/test/kotlin/com/vk/kphpstorm/testing/tests/AddImmutableAnnoIntentionTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package com.vk.kphpstorm.testing.tests | ||
|
|
||
| import com.vk.kphpstorm.intentions.AddImmutableClassAnnotationIntention | ||
| import com.vk.kphpstorm.testing.infrastructure.IntentionTestBase | ||
|
|
||
| class AddImmutableAnnoIntentionTest : IntentionTestBase(AddImmutableClassAnnotationIntention()) { | ||
| fun testAddImmutableAnno1() { | ||
| runIntention("kphp_intentions/immutable_class_intention-1.fixture.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno2() { | ||
| assertNoIntention("kphp_intentions/immutable_class_intention-2.nointention.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno3() { | ||
| assertNoIntention("kphp_intentions/immutable_class_intention-3.nointention.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno4() { | ||
| assertNoIntention("kphp_intentions/immutable_class_intention-4.nointention.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno5() { | ||
| assertNoIntention("kphp_intentions/immutable_class_intention-5.nointention.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno6() { | ||
| runIntention("kphp_intentions/immutable_class_intention-6.fixture.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno7() { | ||
| runIntention("kphp_intentions/immutable_class_intention-7.fixture.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno8() { | ||
| runIntention("kphp_intentions/immutable_class_intention-8.fixture.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno9() { | ||
| runIntention("kphp_intentions/immutable_class_intention-9.fixture.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno10() { | ||
| runIntention("kphp_intentions/immutable_class_intention-10.fixture.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno11() { | ||
| assertNoIntention("kphp_intentions/immutable_class_intention-11.nointent.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno12() { | ||
| assertNoIntention("kphp_intentions/immutable_class_intention-12.nointent.php") | ||
| } | ||
|
|
||
| fun testAddImmutableAnno13() { | ||
| assertNoIntention("kphp_intentions/immutable_class_intention-13.nointent.php") | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.