Skip to content

Commit ac3d58c

Browse files
committed
Fixed names validator for renaming
1 parent abe517f commit ac3d58c

2 files changed

Lines changed: 82 additions & 43 deletions

File tree

src/de/halirutan/mathematica/refactoring/MathematicaNamesValidator.java

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import com.intellij.openapi.project.Project;
2626
import org.jetbrains.annotations.NotNull;
2727

28+
import java.util.regex.Matcher;
29+
import java.util.regex.Pattern;
30+
2831
/**
2932
* For Mathematica syntax, we need special identifier rules because a variable in Mathematica can contain context
3033
* back-ticks. Therefore, this is a valid variable C`B`a.
@@ -36,61 +39,33 @@
3639
*/
3740
public class MathematicaNamesValidator implements NamesValidator {
3841

42+
private Pattern mySymbolPattern;
43+
44+
@SuppressWarnings("WeakerAccess")
45+
public MathematicaNamesValidator() {
46+
final String nc = "\\\\\\[[a-zA-Z]+\\]";
47+
final String symbol = "([$a-zA-Z]|" + nc + ")([$a-zA-Z0-9]|" + nc + ")*";
48+
final String withContext = "`?(" + symbol + "`)*" + symbol;
49+
mySymbolPattern = Pattern.compile(withContext);
50+
51+
}
52+
3953
@Override
4054
public boolean isKeyword(@NotNull final String name, final Project project) {
4155
return false;
4256
}
4357

44-
private enum VariableState {
45-
PREFIX_BACK_TICK,
46-
SYMBOL_START,
47-
SYMBOL_INNER
48-
}
49-
5058
/**
5159
* Makes it possible that a variable can contain back-ticks.
5260
*
53-
* @param name
54-
* name of the variable you like to check
55-
* @param project
56-
* project where the call comes from
61+
* @param name name of the variable you like to check
62+
* @param project project where the call comes from
5763
* @return true if name is a valid Mathematica identifier
5864
*/
5965
@Override
6066
public boolean isIdentifier(@NotNull final String name, final Project project) {
61-
final int len = name.length();
62-
if (len == 0) return false;
63-
64-
VariableState state = VariableState.PREFIX_BACK_TICK;
65-
66-
for (int i = 1; i < len; i++) {
67-
final char ch = name.charAt(i);
68-
switch (state) {
69-
case PREFIX_BACK_TICK:
70-
if (!(Character.isLetter(ch) || ch == '$' || ch == '`')) return false;
71-
else state = VariableState.SYMBOL_START;
72-
break;
73-
case SYMBOL_START:
74-
if (!(Character.isLetter(ch) || ch == '$')) return false;
75-
else state = VariableState.SYMBOL_INNER;
76-
break;
77-
case SYMBOL_INNER:
78-
if (!(Character.isLetterOrDigit(ch) || ch == '$')) {
79-
// several context parts of a variable are separated by a back-tick, but a back-tick cannot be the
80-
// last part, because then it wouldn't be a valid identifier
81-
if (ch == '`' && i != len - 1) {
82-
state = VariableState.SYMBOL_START;
83-
break;
84-
} else {
85-
return false;
86-
}
87-
}
88-
break;
89-
default:
90-
return false;
91-
}
92-
}
93-
return true;
67+
Matcher matcher = mySymbolPattern.matcher(name);
68+
return matcher.matches();
9469
}
9570

9671
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2016 Patrick Scheibe
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy
4+
* of this software and associated documentation files (the "Software"), to deal
5+
* in the Software without restriction, including without limitation the rights
6+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
* copies of the Software, and to permit persons to whom the Software is
8+
* furnished to do so, subject to the following conditions:
9+
*
10+
* The above copyright notice and this permission notice shall be included in
11+
* all copies or substantial portions of the Software.
12+
*
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
* THE SOFTWARE.
20+
*/
21+
22+
package de.halirutan.mathematica.refactoring;
23+
24+
import org.junit.Test;
25+
26+
import java.util.ResourceBundle;
27+
28+
import static org.junit.Assert.assertFalse;
29+
import static org.junit.Assert.assertTrue;
30+
31+
/**
32+
* @author patrick (27.12.16).
33+
*/
34+
public class MathematicaNamesValidatorTest {
35+
36+
private ResourceBundle myNamedCharacters = ResourceBundle.getBundle("de.halirutan.mathematica.codeinsight.completion.namedCharacters");
37+
private ResourceBundle mySymbols = ResourceBundle.getBundle("de.halirutan.mathematica.codeinsight.completion.symbolInformationV11_0_1");
38+
39+
private String myCounterExamples[] = {
40+
"Internal`",
41+
"0Symbol",
42+
"Internal`3",
43+
"Developer`ToPacketArray`"
44+
};
45+
46+
@Test
47+
public void testIsIdentifier() throws Exception {
48+
MathematicaNamesValidator validator = new MathematicaNamesValidator();
49+
for (String nc : myNamedCharacters.keySet()) {
50+
assertTrue(validator.isIdentifier("\\[" + nc + "]", null));
51+
}
52+
53+
for (String symbol : mySymbols.keySet()) {
54+
assertTrue(symbol, validator.isIdentifier(symbol, null));
55+
}
56+
57+
for (String badSymbol : myCounterExamples) {
58+
assertFalse(badSymbol, validator.isIdentifier(badSymbol, null));
59+
}
60+
61+
assertTrue(validator.isIdentifier("Internal`testvar",null));
62+
}
63+
64+
}

0 commit comments

Comments
 (0)