Skip to content

Commit 845bc62

Browse files
committed
Dont check translation strings ending with a colon
Closes: #156
1 parent 64a4d69 commit 845bc62

File tree

10 files changed

+215
-92
lines changed

10 files changed

+215
-92
lines changed

src/main/java/com/cedricziel/idea/typo3/translation/annotation/TranslationAnnotator.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,17 @@ public class TranslationAnnotator implements Annotator {
1313
@Override
1414
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder annotationHolder) {
1515

16-
if (!(psiElement instanceof StringLiteralExpression)) {
16+
if (!(psiElement instanceof StringLiteralExpression) && !(psiElement.getParent() instanceof StringLiteralExpression)) {
1717
return;
1818
}
1919

20-
StringLiteralExpression literalExpression = (StringLiteralExpression) psiElement;
20+
StringLiteralExpression literalExpression;
21+
if (psiElement instanceof StringLiteralExpression) {
22+
literalExpression = (StringLiteralExpression) psiElement;
23+
} else {
24+
literalExpression = (StringLiteralExpression) psiElement.getParent();
25+
}
26+
2127
String value = literalExpression.getContents();
2228

2329
if (TranslationUtil.isTranslationKeyString(value) && value.length() > 4 && !(psiElement.getParent() instanceof ConcatenationExpression)) {
@@ -26,6 +32,10 @@ public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder a
2632
}
2733

2834
private void annotateTranslationUsage(PsiElement psiElement, AnnotationHolder annotationHolder, String value) {
35+
if (value.endsWith(":")) {
36+
return;
37+
}
38+
2939
annotateTranslation(psiElement, annotationHolder, value);
3040
}
3141

src/main/java/com/cedricziel/idea/typo3/translation/codeInspection/TranslationMissingInspection.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,32 @@
22

33
import com.cedricziel.idea.typo3.index.ResourcePathIndex;
44
import com.cedricziel.idea.typo3.util.TranslationUtil;
5+
import com.intellij.codeInspection.LocalInspectionTool;
56
import com.intellij.codeInspection.ProblemsHolder;
7+
import com.intellij.psi.PsiElement;
68
import com.intellij.psi.PsiElementVisitor;
7-
import com.jetbrains.php.lang.inspections.PhpInspection;
89
import com.jetbrains.php.lang.psi.elements.ConcatenationExpression;
910
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
10-
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
1111
import org.jetbrains.annotations.NotNull;
1212

13-
public class TranslationMissingInspection extends PhpInspection {
13+
public class TranslationMissingInspection extends LocalInspectionTool {
1414

1515
public static final String MESSAGE = "Missing translation key";
1616

1717
@NotNull
1818
@Override
1919
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) {
20-
return new PhpElementVisitor() {
20+
return new PsiElementVisitor() {
2121
@Override
22-
public void visitPhpStringLiteralExpression(StringLiteralExpression expression) {
22+
public void visitElement(PsiElement element) {
23+
if (element instanceof StringLiteralExpression) {
24+
visitPhpStringLiteralExpression((StringLiteralExpression) element);
25+
}
26+
27+
super.visitElement(element);
28+
}
29+
30+
private void visitPhpStringLiteralExpression(StringLiteralExpression expression) {
2331
if (expression == null || expression.getParent() instanceof ConcatenationExpression) {
2432
return;
2533
}
@@ -30,6 +38,12 @@ public void visitPhpStringLiteralExpression(StringLiteralExpression expression)
3038
// string references a translation file instead
3139
return;
3240
}
41+
42+
// may be some form of concatenation
43+
if (contents.endsWith(":")) {
44+
return;
45+
}
46+
3347
// new CreateMissingTranslationQuickFix(contents)
3448
problemsHolder.registerProblem(expression, MESSAGE);
3549
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package com.cedricziel.idea.typo3;
2+
3+
import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
4+
import com.intellij.codeInspection.*;
5+
import com.intellij.lang.LanguageAnnotators;
6+
import com.intellij.lang.annotation.Annotation;
7+
import com.intellij.lang.annotation.AnnotationSession;
8+
import com.intellij.lang.annotation.Annotator;
9+
import com.intellij.openapi.util.Pair;
10+
import com.intellij.openapi.util.TextRange;
11+
import com.intellij.psi.PsiElement;
12+
import com.intellij.psi.PsiElementVisitor;
13+
import com.intellij.psi.PsiFile;
14+
import com.intellij.psi.PsiRecursiveElementVisitor;
15+
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
16+
import org.jetbrains.annotations.NotNull;
17+
18+
import java.util.ArrayList;
19+
import java.util.HashSet;
20+
import java.util.List;
21+
import java.util.Set;
22+
23+
abstract public class AbstractTestCase extends LightCodeInsightFixtureTestCase {
24+
private Pair<List<ProblemDescriptor>, Integer> getLocalInspectionsAtCaret(@NotNull String filename, @NotNull String content) {
25+
26+
PsiElement psiFile = myFixture.configureByText(filename, content);
27+
28+
int caretOffset = myFixture.getCaretOffset();
29+
if (caretOffset <= 0) {
30+
fail("Please provide <caret> tag");
31+
}
32+
33+
ProblemsHolder problemsHolder = new ProblemsHolder(InspectionManager.getInstance(getProject()), psiFile.getContainingFile(), false);
34+
35+
for (LocalInspectionEP localInspectionEP : LocalInspectionEP.LOCAL_INSPECTION.getExtensions()) {
36+
Object object = localInspectionEP.getInstance();
37+
if (!(object instanceof LocalInspectionTool)) {
38+
continue;
39+
}
40+
41+
final PsiElementVisitor psiElementVisitor = ((LocalInspectionTool) object).buildVisitor(problemsHolder, false);
42+
43+
psiFile.acceptChildren(new PsiRecursiveElementVisitor() {
44+
@Override
45+
public void visitElement(PsiElement element) {
46+
psiElementVisitor.visitElement(element);
47+
super.visitElement(element);
48+
}
49+
});
50+
51+
psiElementVisitor.visitFile(psiFile.getContainingFile());
52+
}
53+
54+
return Pair.create(problemsHolder.getResults(), caretOffset);
55+
}
56+
57+
public void assertLocalInspectionContains(String filename, String content, String contains) {
58+
Set<String> matches = new HashSet<>();
59+
60+
Pair<List<ProblemDescriptor>, Integer> localInspectionsAtCaret = getLocalInspectionsAtCaret(filename, content);
61+
for (ProblemDescriptor result : localInspectionsAtCaret.getFirst()) {
62+
TextRange textRange = result.getPsiElement().getTextRange();
63+
if (textRange.contains(localInspectionsAtCaret.getSecond()) && result.toString().equals(contains)) {
64+
return;
65+
}
66+
67+
matches.add(result.toString());
68+
}
69+
70+
fail(String.format("Fail matches '%s' with one of %s", contains, matches));
71+
}
72+
73+
public void assertAnnotationContains(String filename, String content, String contains) {
74+
List<String> matches = new ArrayList<>();
75+
for (Annotation annotation : getAnnotationsAtCaret(filename, content)) {
76+
matches.add(annotation.toString());
77+
if (annotation.getMessage().contains(contains)) {
78+
return;
79+
}
80+
}
81+
82+
fail(String.format("Fail matches '%s' with one of %s", contains, matches));
83+
}
84+
85+
public void assertLocalInspectionNotContains(String filename, String content, String contains) {
86+
Pair<List<ProblemDescriptor>, Integer> localInspectionsAtCaret = getLocalInspectionsAtCaret(filename, content);
87+
88+
for (ProblemDescriptor result : localInspectionsAtCaret.getFirst()) {
89+
TextRange textRange = result.getPsiElement().getTextRange();
90+
if (textRange.contains(localInspectionsAtCaret.getSecond()) && result.toString().contains(contains)) {
91+
fail(String.format("Fail inspection not contains '%s'", contains));
92+
}
93+
}
94+
}
95+
96+
public void assertAnnotationNotContains(String filename, String content, String contains) {
97+
for (Annotation annotation : getAnnotationsAtCaret(filename, content)) {
98+
if (annotation.getMessage() != null && annotation.getMessage().contains(contains)) {
99+
fail(String.format("Fail not matching '%s' with '%s'", contains, annotation));
100+
}
101+
}
102+
}
103+
104+
@NotNull
105+
private AnnotationHolderImpl getAnnotationsAtCaret(String filename, String content) {
106+
PsiFile psiFile = myFixture.configureByText(filename, content);
107+
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
108+
109+
AnnotationHolderImpl annotations = new AnnotationHolderImpl(new AnnotationSession(psiFile));
110+
111+
for (Annotator annotator : LanguageAnnotators.INSTANCE.allForLanguage(psiFile.getLanguage())) {
112+
annotator.annotate(psiElement, annotations);
113+
}
114+
115+
return annotations;
116+
}
117+
}

src/test/java/com/cedricziel/idea/typo3/index/TranslationIndexTest.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,15 @@
11
package com.cedricziel.idea.typo3.index;
22

3+
import com.cedricziel.idea.typo3.translation.AbtractTranslationTest;
34
import com.cedricziel.idea.typo3.translation.StubTranslation;
45
import com.cedricziel.idea.typo3.util.TranslationUtil;
5-
import com.intellij.ide.highlighter.XmlFileType;
6-
import com.intellij.openapi.command.WriteCommandAction;
7-
import com.intellij.openapi.fileTypes.FileTypeManager;
8-
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
96
import com.intellij.util.indexing.FileBasedIndex;
107

118
import java.util.Collection;
129
import java.util.Iterator;
1310
import java.util.List;
1411

15-
public class TranslationIndexTest extends LightCodeInsightFixtureTestCase {
16-
@Override
17-
protected void setUp() throws Exception {
18-
super.setUp();
19-
20-
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), () -> {
21-
FileTypeManager.getInstance().associateExtension(XmlFileType.INSTANCE, "xlf");
22-
});
23-
24-
myFixture.addFileToProject("typo3conf/ext/foo/ext_emconf.php", "");
25-
26-
myFixture.copyFileToProject("sample.xlf", "typo3conf/ext/foo/sample.xlf");
27-
myFixture.copyFileToProject("de.sample.xlf", "typo3conf/ext/foo/de.sample.xlf");
28-
}
12+
public class TranslationIndexTest extends AbtractTranslationTest {
2913

3014
@Override
3115
protected String getTestDataPath() {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.cedricziel.idea.typo3.translation;
2+
3+
import com.cedricziel.idea.typo3.AbstractTestCase;
4+
import com.intellij.ide.highlighter.XmlFileType;
5+
import com.intellij.openapi.command.WriteCommandAction;
6+
import com.intellij.openapi.fileTypes.FileTypeManager;
7+
8+
abstract public class AbtractTranslationTest extends AbstractTestCase {
9+
@Override
10+
protected void setUp() throws Exception {
11+
super.setUp();
12+
13+
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), () -> {
14+
FileTypeManager.getInstance().associateExtension(XmlFileType.INSTANCE, "xlf");
15+
});
16+
17+
myFixture.addFileToProject("typo3conf/ext/foo/ext_emconf.php", "");
18+
19+
myFixture.copyFileToProject("sample.xlf", "typo3conf/ext/foo/sample.xlf");
20+
myFixture.copyFileToProject("de.sample.xlf", "typo3conf/ext/foo/de.sample.xlf");
21+
}
22+
23+
@Override
24+
protected String getTestDataPath() {
25+
return "testData/com/cedricziel/idea/typo3/index/translation";
26+
}
27+
}

src/test/java/com/cedricziel/idea/typo3/translation/TranslationReferenceProviderTest.java

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,11 @@
11
package com.cedricziel.idea.typo3.translation;
22

3-
import com.intellij.ide.highlighter.XmlFileType;
4-
import com.intellij.openapi.command.WriteCommandAction;
5-
import com.intellij.openapi.fileTypes.FileTypeManager;
63
import com.intellij.psi.PsiElement;
74
import com.intellij.psi.PsiFile;
85
import com.intellij.psi.PsiReference;
9-
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
106
import com.jetbrains.php.lang.PhpFileType;
117

12-
public class TranslationReferenceProviderTest extends LightCodeInsightFixtureTestCase {
13-
@Override
14-
protected void setUp() throws Exception {
15-
super.setUp();
16-
17-
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), () -> {
18-
FileTypeManager.getInstance().associateExtension(XmlFileType.INSTANCE, "xlf");
19-
});
20-
21-
myFixture.addFileToProject("typo3conf/ext/foo/ext_emconf.php", "");
22-
23-
myFixture.copyFileToProject("sample.xlf", "typo3conf/ext/foo/sample.xlf");
24-
myFixture.copyFileToProject("de.sample.xlf", "typo3conf/ext/foo/de.sample.xlf");
25-
}
26-
27-
@Override
28-
protected String getTestDataPath() {
29-
return "testData/com/cedricziel/idea/typo3/index/translation";
30-
}
8+
public class TranslationReferenceProviderTest extends AbtractTranslationTest {
319

3210
public void testCanCreateTranslationReferencesOnPhpStrings() {
3311
PsiFile file = myFixture.configureByText(PhpFileType.INSTANCE, "<?php \n" +

src/test/java/com/cedricziel/idea/typo3/translation/TranslationReferenceTest.java

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,14 @@
11
package com.cedricziel.idea.typo3.translation;
22

33
import com.intellij.codeInsight.lookup.LookupElement;
4-
import com.intellij.ide.highlighter.XmlFileType;
5-
import com.intellij.openapi.command.WriteCommandAction;
6-
import com.intellij.openapi.fileTypes.FileTypeManager;
74
import com.intellij.psi.PsiElement;
85
import com.intellij.psi.PsiFile;
96
import com.intellij.psi.PsiReference;
107
import com.intellij.psi.ResolveResult;
118
import com.intellij.psi.xml.XmlAttributeValue;
12-
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
139
import com.jetbrains.php.lang.PhpFileType;
1410

15-
public class TranslationReferenceTest extends LightCodeInsightFixtureTestCase {
16-
@Override
17-
protected void setUp() throws Exception {
18-
super.setUp();
19-
20-
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), () -> {
21-
FileTypeManager.getInstance().associateExtension(XmlFileType.INSTANCE, "xlf");
22-
});
23-
24-
myFixture.addFileToProject("typo3conf/ext/foo/ext_emconf.php", "");
25-
26-
myFixture.copyFileToProject("sample.xlf", "typo3conf/ext/foo/sample.xlf");
27-
myFixture.copyFileToProject("de.sample.xlf", "typo3conf/ext/foo/de.sample.xlf");
28-
}
29-
30-
@Override
31-
protected String getTestDataPath() {
32-
return "testData/com/cedricziel/idea/typo3/index/translation";
33-
}
34-
11+
public class TranslationReferenceTest extends AbtractTranslationTest {
3512
public void testReferenceCanResolveDefinition() {
3613
PsiFile file = myFixture.configureByText(PhpFileType.INSTANCE, "<?php \n" +
3714
"\"LLL:EXT:foo/sample.xlf:sys_<caret>language.language_isocode.ab\";");
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.cedricziel.idea.typo3.translation.annotation;
2+
3+
import com.cedricziel.idea.typo3.translation.AbtractTranslationTest;
4+
5+
public class TranslationAnnotatorTest extends AbtractTranslationTest {
6+
public void testCorrectReferenceIsNotMarked() {
7+
assertAnnotationNotContains("foo.php", "<?php \n\"LLL:EXT:foo/sample.xlf:sys_<caret>language.language_isocode.ab\";", "Unresolved translation");
8+
}
9+
10+
public void testInvalidReferenceIsAnnotated() {
11+
assertAnnotationContains("foo.php", "<?php \n\"LLL:EXT:foo/sample.xlf:sys_<caret>language.language_isocode.abc\";", "Unresolved translation");
12+
}
13+
14+
public void testShortenedReferenceIsNotAnnotated() {
15+
assertAnnotationNotContains("foo.php", "<?php \n\"LLL:EXT:foo/sample.xlf:sys_<caret>language.language_isocode.ab\";", "Unresolved translation");
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.cedricziel.idea.typo3.translation.codeInspection;
2+
3+
import com.cedricziel.idea.typo3.translation.AbtractTranslationTest;
4+
5+
public class TranslationMissingInspectionTest extends AbtractTranslationTest {
6+
public void testCorrectReferenceIsNotMarked() {
7+
assertLocalInspectionNotContains("foo.php", "<?php \n\"LLL:EXT:foo/sample.xlf<caret>:sys_language.language_isocode.ab\";", TranslationMissingInspection.MESSAGE);
8+
}
9+
10+
public void testInvalidReferenceIsMarked() {
11+
assertLocalInspectionContains("foo.php", "<?php \n\"LLL:EXT:foo/sample.xlf<caret>:sys_language.language_isocode.abc\";", TranslationMissingInspection.MESSAGE);
12+
}
13+
14+
public void testShortenedReferenceIsNotAnnotated() {
15+
assertLocalInspectionNotContains("foo.php", "<?php \n\"LLL:EXT:foo/sample.xlf<caret>:\";", TranslationMissingInspection.MESSAGE);
16+
}
17+
}

0 commit comments

Comments
 (0)