Skip to content

Commit 606f52e

Browse files
authored
Merge pull request #189 from cedricziel/userfunc-foo
Handle userFunc references
2 parents f89e8c2 + 7e98563 commit 606f52e

File tree

19 files changed

+1204
-70
lines changed

19 files changed

+1204
-70
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ cache:
1616

1717
matrix:
1818
include:
19-
- env: IDEA_VERSION="IU-182.2757.3" PHP_PLUGIN_VERSION="182.2574.13" DEPLOY=true
19+
- env: IDEA_VERSION="IU-182.2757.3" PHP_PLUGIN_VERSION="182.2574.13" PSI_VIEWER_PLUGIN_VERSION=182.2757.2 DEPLOY=true
2020
# - env: IDEA_VERSION="IU-173.4127.17" PHP_PLUGIN_VERSION="173.4127.13"
2121
# allow_failures:
2222
# - env: IDEA_VERSION="IU-173.4127.17" PHP_PLUGIN_VERSION="173.4127.13"
@@ -25,6 +25,7 @@ before_install:
2525
- "export ORG_GRADLE_PROJECT_ideaVersion=${IDEA_VERSION}"
2626
- "export ORG_GRADLE_PROJECT_ideaType=${IDEA_TYPE}"
2727
- "export ORG_GRADLE_PROJECT_phpPluginVersion=${PHP_PLUGIN_VERSION}"
28+
- "export ORG_GRADLE_PROJECT_psiViewerPluginVersion=${PSI_VIEWER_PLUGIN_VERSION}"
2829
- java -version
2930

3031
script:

build.gradle

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ buildscript {
99
}
1010

1111
plugins {
12-
id "org.jetbrains.intellij" version "0.3.2"
13-
id "de.undercouch.download" version "3.2.0"
12+
id "org.jetbrains.intellij" version "0.3.3"
1413
id 'com.palantir.git-version' version "0.9.1"
1514
}
1615

@@ -21,7 +20,14 @@ apply plugin: 'java'
2120
intellij {
2221
version ideaVersion
2322
pluginName 'TYPO3 CMS Plugin'
24-
plugins = ["com.jetbrains.php:${phpPluginVersion}", 'CSS', 'java-i18n', 'properties', 'yaml']
23+
plugins = [
24+
"com.jetbrains.php:${phpPluginVersion}",
25+
'CSS',
26+
'java-i18n',
27+
'properties',
28+
'yaml',
29+
"PsiViewer:${psiViewerPluginVersion}"
30+
]
2531
downloadSources !Boolean.valueOf(System.getenv('CI'))
2632

2733
publishPlugin {
@@ -38,24 +44,6 @@ intellij {
3844
group 'com.cedricziel'
3945
version gitVersion()
4046

41-
apply plugin: 'de.undercouch.download'
42-
task downloadPsiViewerPlugin() {
43-
download {
44-
src 'https://plugins.jetbrains.com/plugin/download?updateId=46431'
45-
dest new File("${buildDir}/tmp/plugins/", 'PsiViewer.jar')
46-
onlyIfNewer true
47-
}
48-
}
49-
50-
task copyPsiViewerPluginToSandBox(type: Copy) {
51-
from "${buildDir}/tmp/plugins/PsiViewer.jar"
52-
into "${buildDir}/idea-sandbox/plugins/"
53-
}
54-
55-
copyPsiViewerPluginToSandBox.dependsOn downloadPsiViewerPlugin
56-
copyPsiViewerPluginToSandBox.mustRunAfter prepareSandbox
57-
runIde.dependsOn copyPsiViewerPluginToSandBox
58-
5947
wrapper {
6048
gradleVersion '4.3.1'
6149
}

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
ideaVersion = IU-182.2757.3
22
phpPluginVersion = 182.2574.13
3+
psiViewerPluginVersion = 182.2757.2
34
#ideaVersion = IU-2018.1.4
45
#phpPluginVersion = 181.5087.24
56
#ideaVersion = IU-2017.3.3

src/main/java/com/cedricziel/idea/typo3/codeInspection/MissingColumnTypeInspection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void visitPhpElement(PhpPsiElement element) {
5050
if (arrayIndex != null && arrayIndex.equals("type")) {
5151
if (element instanceof StringLiteralExpression) {
5252
String tableName = ((StringLiteralExpression) element).getContents();
53-
boolean isValidRenderType = TCAUtil.getAvailableColumnTypes(element).contains(tableName);
53+
boolean isValidRenderType = TCAUtil.getAvailableColumnTypes().contains(tableName);
5454

5555
if (!isValidRenderType) {
5656
problemsHolder.registerProblem(element, "Missing column type definition");
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package com.cedricziel.idea.typo3.tca;
2+
3+
import com.intellij.patterns.ElementPattern;
4+
import com.intellij.patterns.PlatformPatterns;
5+
import com.intellij.patterns.PsiElementPattern;
6+
import com.intellij.psi.PsiElement;
7+
import com.intellij.psi.tree.IElementType;
8+
import com.jetbrains.php.lang.parser.PhpElementTypes;
9+
import com.jetbrains.php.lang.psi.elements.ArrayCreationExpression;
10+
import com.jetbrains.php.lang.psi.elements.ArrayHashElement;
11+
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
12+
import org.jetbrains.annotations.Contract;
13+
import org.jetbrains.annotations.NotNull;
14+
15+
public class TCAPatterns {
16+
@Contract(pure = true)
17+
public static boolean isWizard(@NotNull ArrayCreationExpression expression) {
18+
19+
return isWizard().accepts(expression);
20+
}
21+
22+
@Contract(pure = true)
23+
public static PsiElementPattern.Capture<PsiElement> isWizard() {
24+
25+
return PlatformPatterns.psiElement()
26+
.withSuperParent(5, arrayKeyWithString("wizards", PhpElementTypes.ARRAY_KEY));
27+
}
28+
29+
public static boolean hasArrayHashElement(@NotNull ArrayCreationExpression expression, @NotNull String arrayKey) {
30+
31+
return hasArrayHashElementPattern(arrayKey, null).accepts(expression);
32+
}
33+
34+
public static boolean hasArrayHashElement(@NotNull ArrayCreationExpression expression, @NotNull String arrayKey, String arrayValue) {
35+
36+
return hasArrayHashElementPattern(arrayKey, arrayValue).accepts(expression);
37+
}
38+
39+
public static ElementPattern<PsiElement> hasArrayHashElementPattern(@NotNull String arrayKey) {
40+
return hasArrayHashElementPattern(arrayKey, null);
41+
}
42+
43+
public static ElementPattern<PsiElement> hasArrayHashElementPattern(@NotNull String arrayKey, String arrayValue) {
44+
45+
if (arrayValue != null) {
46+
47+
return PlatformPatterns
48+
.and(
49+
PlatformPatterns.psiElement().withChild(
50+
arrayKeyWithString(arrayKey, PhpElementTypes.ARRAY_KEY)
51+
),
52+
PlatformPatterns.psiElement().withChild(
53+
arrayKeyWithString(arrayValue, PhpElementTypes.ARRAY_VALUE)
54+
)
55+
);
56+
57+
}
58+
59+
return PlatformPatterns.psiElement().withChild(
60+
arrayKeyWithString(arrayKey, PhpElementTypes.ARRAY_KEY)
61+
);
62+
}
63+
64+
private static PsiElementPattern.Capture<ArrayHashElement> arrayKeyWithString(@NotNull String arrayKey, IElementType arrayKey2) {
65+
return PlatformPatterns.psiElement(ArrayHashElement.class).withChild(
66+
elementWithStringLiteral(arrayKey2, arrayKey)
67+
);
68+
}
69+
70+
@NotNull
71+
public static ElementPattern<PsiElement> elementWithStringLiteral(IElementType elementType, @NotNull String value) {
72+
73+
return PlatformPatterns.or(
74+
PlatformPatterns.psiElement(elementType).withText("\"" + value + "\""),
75+
PlatformPatterns.psiElement(elementType).withText("'" + value + "'")
76+
);
77+
}
78+
79+
@NotNull
80+
public static PsiElementPattern.Capture<PsiElement> isEvalColumnValue() {
81+
return arrayAssignmentValueWithIndexPattern("eval");
82+
}
83+
84+
@NotNull
85+
public static PsiElementPattern.Capture<PsiElement> arrayAssignmentValueWithIndexPattern(@NotNull String targetIndex) {
86+
87+
return PlatformPatterns.psiElement().withParent(
88+
PlatformPatterns.psiElement(StringLiteralExpression.class).withParent(
89+
PlatformPatterns.or(
90+
// ['eval' => '<caret>']
91+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_VALUE).withParent(
92+
PlatformPatterns.psiElement(ArrayHashElement.class).withChild(
93+
elementWithStringLiteral(PhpElementTypes.ARRAY_KEY, targetIndex)
94+
)
95+
),
96+
// $GLOBALS['eval'] = '<caret>';
97+
PlatformPatterns.psiElement(PhpElementTypes.ASSIGNMENT_EXPRESSION).withChild(
98+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_ACCESS_EXPRESSION).withChild(
99+
elementWithStringLiteral(PhpElementTypes.ARRAY_INDEX, targetIndex)
100+
)
101+
)
102+
)
103+
)
104+
);
105+
}
106+
107+
@NotNull
108+
public static PsiElementPattern.Capture<PsiElement> arrayAssignmentIndexWithIndexPattern(@NotNull String targetIndex) {
109+
110+
return PlatformPatterns.psiElement().withParent(
111+
PlatformPatterns.psiElement(StringLiteralExpression.class).withParent(
112+
PlatformPatterns.or(
113+
// ['config' => ['<caret>']]
114+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_VALUE).withParent(
115+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_CREATION_EXPRESSION).withParent(
116+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_VALUE).withParent(
117+
PlatformPatterns.psiElement(ArrayHashElement.class).withChild(
118+
elementWithStringLiteral(PhpElementTypes.ARRAY_KEY, targetIndex)
119+
)
120+
)
121+
)
122+
),
123+
// ['config' => ['<caret>' => '']]
124+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_KEY).withParent(
125+
PlatformPatterns.psiElement(ArrayHashElement.class).withParent(
126+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_CREATION_EXPRESSION).withParent(
127+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_VALUE).withParent(
128+
PlatformPatterns.psiElement(ArrayHashElement.class).withChild(
129+
elementWithStringLiteral(PhpElementTypes.ARRAY_KEY, targetIndex)
130+
)
131+
)
132+
)
133+
)
134+
),
135+
// $GLOBALS['<caret>'] = '';
136+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_INDEX).withParent(
137+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_ACCESS_EXPRESSION).withChild(
138+
PlatformPatterns.psiElement(PhpElementTypes.ARRAY_ACCESS_EXPRESSION).withChild(
139+
elementWithStringLiteral(PhpElementTypes.ARRAY_INDEX, targetIndex)
140+
)
141+
)
142+
)
143+
)
144+
)
145+
);
146+
}
147+
148+
@NotNull
149+
public static ElementPattern<? extends PsiElement> isIndexInParentIndex(@NotNull String targetParentIndex) {
150+
151+
return arrayAssignmentIndexWithIndexPattern(targetParentIndex);
152+
}
153+
}

src/main/java/com/cedricziel/idea/typo3/tca/codeInsight/TCACompletionContributor.java

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
package com.cedricziel.idea.typo3.tca.codeInsight;
22

3-
import com.cedricziel.idea.typo3.psi.PhpElementsUtil;
3+
import com.cedricziel.idea.typo3.TYPO3CMSIcons;
4+
import com.cedricziel.idea.typo3.tca.TCAPatterns;
45
import com.cedricziel.idea.typo3.util.TCAUtil;
5-
import com.cedricziel.idea.typo3.util.TableUtil;
66
import com.intellij.codeInsight.completion.*;
7-
import com.intellij.codeInsight.lookup.LookupElement;
8-
import com.intellij.psi.PsiElement;
7+
import com.intellij.codeInsight.lookup.LookupElementBuilder;
98
import com.intellij.util.ProcessingContext;
9+
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
10+
import org.apache.commons.lang.StringUtils;
1011
import org.jetbrains.annotations.NotNull;
1112

12-
import static com.cedricziel.idea.typo3.psi.PhpElementsUtil.extractArrayIndexFromValue;
13-
import static com.cedricziel.idea.typo3.util.TCAUtil.arrayIndexIsTCATableNameField;
14-
1513
public class TCACompletionContributor extends CompletionContributor {
1614

1715
public TCACompletionContributor() {
@@ -20,23 +18,12 @@ public TCACompletionContributor() {
2018
*/
2119
extend(
2220
CompletionType.BASIC,
23-
PhpElementsUtil.isStringArrayValue(),
21+
TCAPatterns.arrayAssignmentValueWithIndexPattern("renderType"),
2422
new CompletionProvider<CompletionParameters>() {
2523
@Override
2624
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
27-
PsiElement element = parameters.getPosition();
28-
29-
String arrayIndex = extractArrayIndexFromValue(element);
30-
if ("renderType".equals(arrayIndex)) {
31-
for(String name: TCAUtil.getAvailableRenderTypes(element)) {
32-
result.addElement(new LookupElement() {
33-
@NotNull
34-
@Override
35-
public String getLookupString() {
36-
return name;
37-
}
38-
});
39-
}
25+
for (String renderType: TCAUtil.getAvailableRenderTypes(parameters.getPosition())) {
26+
result.addElement(LookupElementBuilder.create(renderType).withIcon(TYPO3CMSIcons.TYPO3_ICON));
4027
}
4128
}
4229
}
@@ -47,24 +34,73 @@ public String getLookupString() {
4734
*/
4835
extend(
4936
CompletionType.BASIC,
50-
PhpElementsUtil.isStringArrayValue(),
37+
TCAPatterns.arrayAssignmentValueWithIndexPattern("type"),
38+
new CompletionProvider<CompletionParameters>() {
39+
@Override
40+
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
41+
for (String columnType: TCAUtil.getAvailableColumnTypes()) {
42+
result.addElement(LookupElementBuilder.create(columnType).withIcon(TYPO3CMSIcons.TYPO3_ICON));
43+
}
44+
}
45+
}
46+
);
47+
48+
/*
49+
* Complete available 'eval' values in TCA
50+
*/
51+
extend(
52+
CompletionType.BASIC,
53+
TCAPatterns.isEvalColumnValue(),
5154
new CompletionProvider<CompletionParameters>() {
5255
@Override
5356
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
54-
PsiElement element = parameters.getPosition();
5557

56-
String arrayIndex = extractArrayIndexFromValue(element);
57-
if ("type".equals(arrayIndex)) {
58-
for(String name: TCAUtil.getAvailableColumnTypes(element)) {
59-
result.addElement(new LookupElement() {
60-
@NotNull
61-
@Override
62-
public String getLookupString() {
63-
return name;
64-
}
65-
});
58+
StringLiteralExpression literalExpression = (StringLiteralExpression) parameters.getOriginalPosition().getParent();
59+
if (literalExpression == null) {
60+
return;
61+
}
62+
63+
for (String evaluationName: TCAUtil.getAvailableEvaluations()) {
64+
result.addElement(LookupElementBuilder.create(evaluationName).withIcon(TYPO3CMSIcons.TYPO3_ICON));
65+
}
66+
67+
int lastIndexOf = StringUtils.lastIndexOf(literalExpression.getContents(), ",");
68+
if (lastIndexOf != -1 && literalExpression.getContents().length() == lastIndexOf + 1) {
69+
for (String evaluationName: TCAUtil.getAvailableEvaluations()) {
70+
LookupElementBuilder element = LookupElementBuilder.create(literalExpression.getContents() + evaluationName)
71+
.withPresentableText(evaluationName)
72+
.withIcon(TYPO3CMSIcons.TYPO3_ICON);
73+
74+
result.addElement(element);
6675
}
6776
}
77+
78+
if (lastIndexOf != -1 && literalExpression.getContents().length() >= lastIndexOf + 1) {
79+
for (String evaluationName: TCAUtil.getAvailableEvaluations()) {
80+
String newExpression = literalExpression.getContents().substring(0, lastIndexOf) + "," + evaluationName;
81+
LookupElementBuilder element = LookupElementBuilder.create(newExpression)
82+
.withPresentableText(evaluationName)
83+
.withIcon(TYPO3CMSIcons.TYPO3_ICON);
84+
85+
result.addElement(element);
86+
}
87+
}
88+
}
89+
}
90+
);
91+
92+
/*
93+
* Complete available 'config' options in TCA
94+
*/
95+
extend(
96+
CompletionType.BASIC,
97+
TCAPatterns.isIndexInParentIndex("config"),
98+
new CompletionProvider<CompletionParameters>() {
99+
@Override
100+
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
101+
for (String evaluationName: TCAUtil.getConfigSectionChildren()) {
102+
result.addElement(LookupElementBuilder.create(evaluationName).withIcon(TYPO3CMSIcons.TYPO3_ICON));
103+
}
68104
}
69105
}
70106
);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.cedricziel.idea.typo3.userFunc;
2+
3+
import com.intellij.codeInsight.completion.InsertHandler;
4+
import com.intellij.codeInsight.completion.InsertionContext;
5+
6+
public class UserFuncInsertHandler implements InsertHandler<UserFuncLookupElement> {
7+
private static final UserFuncInsertHandler INSTANCE = new UserFuncInsertHandler();
8+
9+
public static UserFuncInsertHandler getInstance() {
10+
return INSTANCE;
11+
}
12+
13+
@Override
14+
public void handleInsert(InsertionContext context, UserFuncLookupElement item) {
15+
16+
}
17+
}

0 commit comments

Comments
 (0)