Skip to content

Commit dfc692e

Browse files
authored
Merge pull request apache#8455 from mbien/fix-js-typedtextinterceptor-test
Fix race condition in JavaScript TextInterceptorTests
2 parents a1ad61d + e7a32d0 commit dfc692e

File tree

6 files changed

+71
-67
lines changed

6 files changed

+71
-67
lines changed

ide/db.sql.editor/src/org/netbeans/modules/db/sql/editor/OptionsUtils.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.netbeans.modules.db.sql.editor;
2121

22-
import java.util.concurrent.atomic.AtomicBoolean;
2322
import java.util.prefs.PreferenceChangeEvent;
2423
import java.util.prefs.PreferenceChangeListener;
2524
import java.util.prefs.Preferences;
@@ -35,7 +34,6 @@ public final class OptionsUtils {
3534
public static final String PAIR_CHARACTERS_COMPLETION = "pair-characters-completion"; //NOI18N
3635
public static final String SQL_AUTO_COMPLETION_SUBWORDS = "sql-completion-subwords"; //NOI18N
3736
public static final boolean SQL_AUTO_COMPLETION_SUBWORDS_DEFAULT = false;
38-
private static final AtomicBoolean INITED = new AtomicBoolean(false);
3937

4038
private static final PreferenceChangeListener PREFERENCES_TRACKER = new PreferenceChangeListener() {
4139
@Override
@@ -54,8 +52,8 @@ public void preferenceChange(PreferenceChangeEvent evt) {
5452

5553
private static Preferences preferences;
5654

57-
private static boolean pairCharactersCompletion = true;
58-
private static boolean sqlCompletionSubwords = SQL_AUTO_COMPLETION_SUBWORDS_DEFAULT;
55+
private static volatile boolean pairCharactersCompletion = true;
56+
private static volatile boolean sqlCompletionSubwords = SQL_AUTO_COMPLETION_SUBWORDS_DEFAULT;
5957

6058
private OptionsUtils() {
6159
}
@@ -80,8 +78,8 @@ public static boolean isSqlCompletionSubwords() {
8078
return sqlCompletionSubwords;
8179
}
8280

83-
private static void lazyInit() {
84-
if (INITED.compareAndSet(false, true)) {
81+
private synchronized static void lazyInit() {
82+
if (preferences == null) {
8583
preferences = MimeLookup.getLookup(SQLLanguageConfig.mimeType).lookup(Preferences.class);
8684
preferences.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, PREFERENCES_TRACKER, preferences));
8785
PREFERENCES_TRACKER.preferenceChange(null);

php/php.editor/src/org/netbeans/modules/php/editor/options/OptionsUtils.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.netbeans.modules.php.editor.options;
2121

22-
import java.util.concurrent.atomic.AtomicBoolean;
2322
import java.util.prefs.PreferenceChangeEvent;
2423
import java.util.prefs.PreferenceChangeListener;
2524
import java.util.prefs.Preferences;
@@ -31,7 +30,6 @@
3130
* @author Tomas Mysik
3231
*/
3332
public final class OptionsUtils {
34-
private static final AtomicBoolean INITED = new AtomicBoolean(false);
3533

3634
private static final PreferenceChangeListener PREFERENCES_TRACKER = new PreferenceChangeListener() {
3735
@Override
@@ -145,22 +143,22 @@ public void preferenceChange(PreferenceChangeEvent evt) {
145143

146144
private static Preferences preferences;
147145

148-
private static Boolean autoCompletionFull = null;
149-
private static Boolean autoCompletionVariables = null;
150-
private static Boolean autoCompletionTypes = null;
151-
private static Boolean autoCompletionNamespaces = null;
152-
private static Boolean autoCompletionSmartQuotes = null;
153-
private static Boolean autoStringConcatination = null;
154-
private static Boolean autoCompletionUseLowercaseTrueFalseNull = null;
155-
private static Boolean autoCompletionCommentAsterisk = null;
156-
157-
private static Boolean codeCompletionStaticMethods = null;
158-
private static Boolean codeCompletionNonStaticMethods = null;
159-
private static Boolean codeCompletionSmartParametersPreFilling = null;
160-
private static Boolean codeCompletionFirstClassCallable = null;
161-
private static Boolean autoImport = null;
162-
private static Boolean autoImportFileScope = null;
163-
private static Boolean autoImportNamespaceScope = null;
146+
private static volatile Boolean autoCompletionFull = null;
147+
private static volatile Boolean autoCompletionVariables = null;
148+
private static volatile Boolean autoCompletionTypes = null;
149+
private static volatile Boolean autoCompletionNamespaces = null;
150+
private static volatile Boolean autoCompletionSmartQuotes = null;
151+
private static volatile Boolean autoStringConcatination = null;
152+
private static volatile Boolean autoCompletionUseLowercaseTrueFalseNull = null;
153+
private static volatile Boolean autoCompletionCommentAsterisk = null;
154+
155+
private static volatile Boolean codeCompletionStaticMethods = null;
156+
private static volatile Boolean codeCompletionNonStaticMethods = null;
157+
private static volatile Boolean codeCompletionSmartParametersPreFilling = null;
158+
private static volatile Boolean codeCompletionFirstClassCallable = null;
159+
private static volatile Boolean autoImport = null;
160+
private static volatile Boolean autoImportFileScope = null;
161+
private static volatile Boolean autoImportNamespaceScope = null;
164162

165163
private static CodeCompletionPanel.VariablesScope codeCompletionVariablesScope = null;
166164

@@ -363,8 +361,8 @@ public static boolean autoImportNamespaceScope() {
363361
return autoImportNamespaceScope;
364362
}
365363

366-
private static void lazyInit() {
367-
if (INITED.compareAndSet(false, true)) {
364+
private synchronized static void lazyInit() {
365+
if (preferences == null) {
368366
preferences = MimeLookup.getLookup(FileUtils.PHP_MIME_TYPE).lookup(Preferences.class);
369367
preferences.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, PREFERENCES_TRACKER, preferences));
370368
PREFERENCES_TRACKER.preferenceChange(null);

php/php.twig/src/org/netbeans/modules/php/twig/editor/ui/options/OptionsUtils.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
*/
1919
package org.netbeans.modules.php.twig.editor.ui.options;
2020

21-
import java.util.concurrent.atomic.AtomicBoolean;
2221
import java.util.prefs.PreferenceChangeEvent;
2322
import java.util.prefs.PreferenceChangeListener;
2423
import java.util.prefs.Preferences;
@@ -31,13 +30,11 @@
3130
*/
3231
public final class OptionsUtils {
3332

34-
private static final AtomicBoolean INITED = new AtomicBoolean(false);
35-
3633
public static final String AUTO_COMPLETION_SMART_QUOTES = "twigAutoCompletionSmartQuotes"; // NOI18N
3734
public static final String AUTO_COMPLETION_SMART_DELIMITERS = "twigAutoCompletionSmartDelimiters"; // NOI18N
3835

39-
private static Boolean autoCompletionSmartQuotes = null;
40-
private static Boolean autoCompletionSmartDelimiters = null;
36+
private static volatile Boolean autoCompletionSmartQuotes = null;
37+
private static volatile Boolean autoCompletionSmartDelimiters = null;
4138

4239
// default values
4340
public static final boolean AUTO_COMPLETION_SMART_QUOTES_DEFAULT = true;
@@ -78,8 +75,8 @@ public static boolean autoCompletionSmartDelimiters() {
7875
return autoCompletionSmartDelimiters;
7976
}
8077

81-
private static void lazyInit() {
82-
if (INITED.compareAndSet(false, true)) {
78+
private synchronized static void lazyInit() {
79+
if (PREFERENCES == null) {
8380
PREFERENCES = MimeLookup.getLookup(TwigLanguage.TWIG_MIME_TYPE).lookup(Preferences.class);
8481
PREFERENCES.addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, PREFERENCES_TRACKER, PREFERENCES));
8582
PREFERENCES_TRACKER.preferenceChange(null);

webcommon/javascript2.editor/src/org/netbeans/modules/javascript2/editor/options/OptionsUtils.java

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import java.util.Map;
2323
import java.util.WeakHashMap;
24-
import java.util.concurrent.atomic.AtomicBoolean;
2524
import java.util.prefs.PreferenceChangeEvent;
2625
import java.util.prefs.PreferenceChangeListener;
2726
import java.util.prefs.Preferences;
@@ -54,11 +53,17 @@ public final class OptionsUtils {
5453
public static final boolean AUTO_COMPLETION_AFTER_DOT_DEFAULT = true;
5554
public static final int COMPETION_ITEM_SIGNATURE_WIDTH_DEFAULT = 40;
5655

57-
private final AtomicBoolean inited = new AtomicBoolean(false);
56+
private boolean testDisableUpdater = false;
5857

59-
private final PreferenceChangeListener preferencesTracker = new PreferenceChangeListener() {
58+
// updates the cached values some time after a change was made
59+
private final PreferenceChangeListener asyncPreferencesUpdater = new PreferenceChangeListener() {
6060
@Override
6161
public void preferenceChange(PreferenceChangeEvent evt) {
62+
63+
if (testDisableUpdater && evt != null) {
64+
return;
65+
}
66+
6267
String settingName = evt == null ? null : evt.getKey();
6368

6469
if (settingName == null || AUTO_COMPLETION_TYPE_RESOLUTION.equals(settingName)) {
@@ -101,24 +106,20 @@ public void preferenceChange(PreferenceChangeEvent evt) {
101106

102107
private Preferences preferences;
103108

104-
private Boolean autoCompletionTypeResolution = null;
105-
private Boolean autoCompletionSmartQuotes = null;
106-
private Boolean autoStringConcatination = null;
107-
private Boolean autoCompletionFull = null;
108-
private Boolean autoCompletionAfterDot = null;
109-
private Integer codeCompletionItemSignatureWidth = null;
109+
// updated outside of EDT
110+
private volatile Boolean autoCompletionTypeResolution = null;
111+
private volatile Boolean autoCompletionSmartQuotes = null;
112+
private volatile Boolean autoStringConcatination = null;
113+
private volatile Boolean autoCompletionFull = null;
114+
private volatile Boolean autoCompletionAfterDot = null;
115+
private volatile Integer codeCompletionItemSignatureWidth = null;
110116

111117
private OptionsUtils(Language<JsTokenId> language) {
112118
this.mimeType = language.mimeType();
113119
}
114120

115121
public static synchronized OptionsUtils forLanguage(Language<JsTokenId> language) {
116-
OptionsUtils instance = INSTANCES.get(language);
117-
if (instance == null) {
118-
instance = new OptionsUtils(language);
119-
INSTANCES.put(language, instance);
120-
}
121-
return instance;
122+
return INSTANCES.computeIfAbsent(language, OptionsUtils::new);
122123
}
123124

124125
/**
@@ -173,24 +174,27 @@ public boolean autoCompletionAfterDot() {
173174
return autoCompletionAfterDot;
174175
}
175176

176-
private void lazyInit() {
177-
if (inited.compareAndSet(false, true)) {
177+
private synchronized void lazyInit() {
178+
if (preferences == null) {
178179
preferences = MimeLookup.getLookup(mimeType).lookup(Preferences.class);
179180
preferences.addPreferenceChangeListener(WeakListeners.create(
180-
PreferenceChangeListener.class, preferencesTracker, preferences));
181-
preferencesTracker.preferenceChange(null);
181+
PreferenceChangeListener.class, asyncPreferencesUpdater, preferences));
182+
asyncPreferencesUpdater.preferenceChange(null);
182183
}
183184
}
184185

185-
public void setTestTypeResolution(boolean value) {
186-
autoCompletionTypeResolution = value;
186+
// for tests
187+
188+
public void setTestTypeResolution(boolean overwrite) {
189+
autoCompletionTypeResolution = overwrite;
190+
}
191+
192+
public void setTestCompletionSmartQuotes(boolean overwrite) {
193+
autoCompletionSmartQuotes = overwrite;
187194
}
188195

189-
/**
190-
*
191-
* @param width number of chars of max width of signature
192-
*/
193-
public void setCodeCompletionItemSignatureWidth(int width) {
194-
codeCompletionItemSignatureWidth = width;
196+
public void setTestDisablePreferencesTracking() {
197+
testDisableUpdater = true;
195198
}
199+
196200
}

webcommon/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/JsDeletedTextInterceptorTest.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@ public JsDeletedTextInterceptorTest(String testName) {
4747
super(testName);
4848
}
4949

50-
5150
@Override
5251
protected void setUp() throws Exception {
5352
super.setUp();
53+
@SuppressWarnings("unchecked")
54+
OptionsUtils options = OptionsUtils.forLanguage(getPreferredLanguage().getLexerLanguage());
55+
options.setTestDisablePreferencesTracking();
56+
options.setTestCompletionSmartQuotes(OptionsUtils.AUTO_COMPLETION_SMART_QUOTES_DEFAULT);
5457
MimeLookup.getLookup(JsTokenId.JAVASCRIPT_MIME_TYPE).lookup(Preferences.class).clear();
5558
}
5659

@@ -194,15 +197,15 @@ public void run() {
194197
}
195198
}
196199

200+
@SuppressWarnings("unchecked")
197201
public void testDisabledSmartQuotes1() throws Exception {
198-
MimeLookup.getLookup(JsTokenId.JAVASCRIPT_MIME_TYPE).lookup(Preferences.class)
199-
.putBoolean(OptionsUtils.AUTO_COMPLETION_SMART_QUOTES, false);
202+
OptionsUtils.forLanguage(getPreferredLanguage().getLexerLanguage()).setTestCompletionSmartQuotes(false);
200203
deleteChar("x = \"^\"", "x = ^\"");
201204
}
202205

206+
@SuppressWarnings("unchecked")
203207
public void testDisabledSmartQuotes2() throws Exception {
204-
MimeLookup.getLookup(JsTokenId.JAVASCRIPT_MIME_TYPE).lookup(Preferences.class)
205-
.putBoolean(OptionsUtils.AUTO_COMPLETION_SMART_QUOTES, false);
208+
OptionsUtils.forLanguage(getPreferredLanguage().getLexerLanguage()).setTestCompletionSmartQuotes(false);
206209
deleteChar("x = `^`", "x = ^`");
207210
}
208211

webcommon/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/JsTypedTextInterceptorTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,12 @@ public JsTypedTextInterceptorTest(String testName) {
4444
}
4545

4646
@Override
47+
@SuppressWarnings("unchecked")
4748
protected void setUp() throws Exception {
4849
super.setUp();
50+
OptionsUtils options = OptionsUtils.forLanguage(getPreferredLanguage().getLexerLanguage());
51+
options.setTestDisablePreferencesTracking();
52+
options.setTestCompletionSmartQuotes(OptionsUtils.AUTO_COMPLETION_SMART_QUOTES_DEFAULT);
4953
MimeLookup.getLookup(JsTokenId.JAVASCRIPT_MIME_TYPE).lookup(Preferences.class).clear();
5054
}
5155

@@ -332,9 +336,9 @@ public void testEnabledSmartQuotes() throws Exception {
332336
insertChar("x = ^", '"', "x = \"^\"");
333337
}
334338

339+
@SuppressWarnings("unchecked")
335340
public void testDisabledSmartQuotes() throws Exception {
336-
MimeLookup.getLookup(JsTokenId.JAVASCRIPT_MIME_TYPE).lookup(Preferences.class)
337-
.putBoolean(OptionsUtils.AUTO_COMPLETION_SMART_QUOTES, false);
341+
OptionsUtils.forLanguage(getPreferredLanguage().getLexerLanguage()).setTestCompletionSmartQuotes(false);
338342
insertChar("x = ^", '"', "x = \"^");
339343
}
340344

0 commit comments

Comments
 (0)