mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
Spellchecker: WI-27124 reload dictionary on externals changes: custom dictionaries case (.dic) + tests [IDEA-CR-23546]
This commit is contained in:
@@ -22,6 +22,9 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
import com.intellij.openapi.vfs.VirtualFileListener;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl;
|
||||
import com.intellij.spellchecker.dictionary.EditableDictionary;
|
||||
@@ -31,7 +34,6 @@ import com.intellij.spellchecker.engine.SpellCheckerFactory;
|
||||
import com.intellij.spellchecker.engine.SuggestionProvider;
|
||||
import com.intellij.spellchecker.settings.SpellCheckerSettings;
|
||||
import com.intellij.spellchecker.state.AggregatedDictionaryState;
|
||||
import com.intellij.spellchecker.util.SPFileUtil;
|
||||
import com.intellij.spellchecker.util.Strings;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -41,6 +43,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.openapi.util.io.FileUtil.isAncestor;
|
||||
import static com.intellij.spellchecker.util.SPFileUtil.processFilesRecursively;
|
||||
|
||||
public class SpellCheckerManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.SpellCheckerManager");
|
||||
|
||||
@@ -61,6 +66,38 @@ public class SpellCheckerManager {
|
||||
this.project = project;
|
||||
this.settings = settings;
|
||||
fullConfigurationReload();
|
||||
LocalFileSystem.getInstance().addVirtualFileListener(new VirtualFileListener() {
|
||||
@Override
|
||||
public void fileDeleted(@NotNull VirtualFileEvent event) {
|
||||
final String path = event.getFile().getPath();
|
||||
if (spellChecker.isDictionaryLoad(path)) {
|
||||
spellChecker.removeDictionary(path);
|
||||
restartInspections();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileCreated(@NotNull VirtualFileEvent event) {
|
||||
final String path = event.getFile().getPath();
|
||||
boolean customDic = path.endsWith(".dic") && settings.getDictionaryFoldersPaths().stream().anyMatch(i -> isAncestor(i, path, true));
|
||||
if (customDic) {
|
||||
spellChecker.loadDictionary(new FileLoader(path, path));
|
||||
restartInspections();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contentsChanged(@NotNull VirtualFileEvent event) {
|
||||
final String path = event.getFile().getPath();
|
||||
if (settings.getDisabledDictionariesPaths().contains(path)) return;
|
||||
|
||||
if (spellChecker.isDictionaryLoad(path)) {
|
||||
spellChecker.removeDictionary(path);
|
||||
spellChecker.loadDictionary(new FileLoader(path, path));
|
||||
restartInspections();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void fullConfigurationReload() {
|
||||
@@ -91,8 +128,8 @@ public class SpellCheckerManager {
|
||||
if (settings != null && settings.getDictionaryFoldersPaths() != null) {
|
||||
final Set<String> disabledDictionaries = settings.getDisabledDictionariesPaths();
|
||||
for (String folder : settings.getDictionaryFoldersPaths()) {
|
||||
SPFileUtil.processFilesRecursively(folder, s -> {
|
||||
boolean dictionaryShouldBeLoad =!disabledDictionaries.contains(s);
|
||||
processFilesRecursively(folder, s -> {
|
||||
boolean dictionaryShouldBeLoad = !disabledDictionaries.contains(s);
|
||||
boolean dictionaryIsLoad = spellChecker.isDictionaryLoad(s);
|
||||
if (dictionaryIsLoad && !dictionaryShouldBeLoad) {
|
||||
spellChecker.removeDictionary(s);
|
||||
@@ -142,7 +179,7 @@ public class SpellCheckerManager {
|
||||
if (settings != null && settings.getDictionaryFoldersPaths() != null) {
|
||||
final Set<String> disabledDictionaries = settings.getDisabledDictionariesPaths();
|
||||
for (String folder : settings.getDictionaryFoldersPaths()) {
|
||||
SPFileUtil.processFilesRecursively(folder, s -> {
|
||||
processFilesRecursively(folder, s -> {
|
||||
if (!disabledDictionaries.contains(s)) {
|
||||
loaders.add(new FileLoader(s, s));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "<TYPO descr="Typo: In word 'newword'">newword</TYPO>";
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "<TYPO descr="Typo: In word 'newword'">newword</TYPO>";
|
||||
@@ -0,0 +1 @@
|
||||
anotherword
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "newword";
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "<TYPO descr="Typo: In word 'newword'">newword</TYPO>";
|
||||
@@ -0,0 +1 @@
|
||||
newword
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
echo "
|
||||
newword
|
||||
anotherword
|
||||
";
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
echo "
|
||||
newword
|
||||
<TYPO descr="Typo: In word 'anotherword'">anotherword</TYPO>
|
||||
";
|
||||
@@ -0,0 +1,2 @@
|
||||
newword
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
anotherword
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
echo "newword
|
||||
anotherword
|
||||
firstword
|
||||
secondword
|
||||
thirdword";
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
echo "newword
|
||||
anotherword
|
||||
<TYPO descr="Typo: In word 'firstword'">firstword</TYPO>
|
||||
<TYPO descr="Typo: In word 'secondword'">secondword</TYPO>
|
||||
<TYPO descr="Typo: In word 'thirdword'">thirdword</TYPO>";
|
||||
@@ -0,0 +1,2 @@
|
||||
newword
|
||||
anotherword
|
||||
@@ -0,0 +1,5 @@
|
||||
newword
|
||||
anotherword
|
||||
firstword
|
||||
secondword
|
||||
thirdword
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "newword";
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "<TYPO descr="Typo: In word 'newword'">newword</TYPO>";
|
||||
@@ -0,0 +1 @@
|
||||
newword
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
echo "<TYPO descr="Typo: In word 'firstword'">firstword</TYPO>
|
||||
secondword
|
||||
thirdword
|
||||
fourthword";
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
echo "firstword
|
||||
secondword
|
||||
thirdword
|
||||
<TYPO descr="Typo: In word 'fourthword'">fourthword</TYPO>";
|
||||
@@ -0,0 +1,3 @@
|
||||
firstword
|
||||
secondword
|
||||
thirdword
|
||||
@@ -0,0 +1,3 @@
|
||||
secondword
|
||||
thirdword
|
||||
fourthword
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "<TYPO descr="Typo: In word 'newword'">newword</TYPO>";
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "newword";
|
||||
@@ -0,0 +1 @@
|
||||
newword
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "<TYPO descr="Typo: In word 'newword'">newword</TYPO>";
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
echo "newword";
|
||||
@@ -0,0 +1 @@
|
||||
newword
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
echo "
|
||||
<TYPO descr="Typo: In word 'newword'">newword</TYPO>
|
||||
anotherword
|
||||
";
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
echo "
|
||||
newword
|
||||
anotherword
|
||||
";
|
||||
@@ -0,0 +1 @@
|
||||
newword
|
||||
@@ -0,0 +1 @@
|
||||
anotherword
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.spellchecker.dictionary;
|
||||
|
||||
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.spellchecker.SpellCheckerManager;
|
||||
import com.intellij.spellchecker.inspection.SpellcheckerInspectionTestCase;
|
||||
import com.intellij.spellchecker.settings.SpellCheckerSettings;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.openapi.vfs.VfsUtil.findFileByIoFile;
|
||||
|
||||
public class CustomDictionaryTest extends SpellcheckerInspectionTestCase {
|
||||
private static final String TEST_DIC = "test.dic";
|
||||
private static final String NEW_TEST_DIC = "new_" + TEST_DIC;
|
||||
private static final String TEST_DIC_AFTER = TEST_DIC + ".after";
|
||||
private static final String TEMP_DIC = TEST_DIC + ".temp";
|
||||
private List<String> oldPaths;
|
||||
SpellCheckerSettings settings;
|
||||
SpellCheckerManager spellCheckerManager;
|
||||
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
settings = SpellCheckerSettings.getInstance(getProject());
|
||||
spellCheckerManager = SpellCheckerManager.getInstance(getProject());
|
||||
oldPaths = settings.getDictionaryFoldersPaths();
|
||||
settings.setDictionaryFoldersPaths(Collections.singletonList(getTestDictDirectory()));
|
||||
spellCheckerManager.fullConfigurationReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
//noinspection SuperTearDownInFinally
|
||||
super.tearDown();
|
||||
settings.setDictionaryFoldersPaths(oldPaths);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return Paths.get(getSpellcheckerTestDataPath(), "inspection", "dictionary").toString();
|
||||
}
|
||||
|
||||
private String getTestDictionary() {
|
||||
return Paths.get(getTestDictDirectory(), TEST_DIC).toString();
|
||||
}
|
||||
|
||||
private String getTestDictDirectory() {
|
||||
return Paths.get(myFixture.getTestDataPath(), getTestName(true)).toString();
|
||||
}
|
||||
|
||||
private VirtualFile getTestDictionaryFile() {
|
||||
return findFileByIoFile(Paths.get(getTestDictionary()).toFile(), true);
|
||||
}
|
||||
|
||||
private String loadFromTestDictionary() throws IOException {
|
||||
final VirtualFile file = findFileByIoFile(new File(getTestDictionary()), true);
|
||||
if (file == null) return null;
|
||||
return VfsUtilCore.loadText(file);
|
||||
}
|
||||
|
||||
private void modifyDictContent(String newContent) throws IOException {
|
||||
WriteAction.run(() -> VfsUtil.saveText(getTestDictionaryFile(), newContent));
|
||||
}
|
||||
|
||||
private void doBeforeCheck() {
|
||||
doTest(Paths.get(getTestDictDirectory(), "test.before.php").toString());
|
||||
}
|
||||
|
||||
private void doAfterCheck() {
|
||||
doTest(Paths.get(getTestDictDirectory(), "test.after.php").toString());
|
||||
}
|
||||
|
||||
private void doTest() throws IOException {
|
||||
final String oldDictContent = loadFromTestDictionary();
|
||||
try {
|
||||
doBeforeCheck();
|
||||
modifyDictContent(VfsUtilCore.loadText(findFileByIoFile(Paths.get(getTestDictDirectory(), TEST_DIC_AFTER).toFile(), true)));
|
||||
doAfterCheck();
|
||||
}
|
||||
finally {
|
||||
//back to initial state
|
||||
modifyDictContent(oldDictContent);
|
||||
}
|
||||
}
|
||||
|
||||
private void doNewDictTest() throws IOException {
|
||||
final VirtualFile file = findFileByIoFile(Paths.get(getTestDictDirectory(), TEST_DIC_AFTER).toFile(), true);
|
||||
try {
|
||||
doBeforeCheck();
|
||||
WriteAction.run(() -> file.copy(this, file.getParent(), NEW_TEST_DIC));
|
||||
doAfterCheck();
|
||||
}
|
||||
finally {
|
||||
//back to initial state
|
||||
WriteAction.run(() -> file.getParent().findChild(NEW_TEST_DIC).delete(this));
|
||||
}
|
||||
}
|
||||
|
||||
private void doRemoveDictTest() throws IOException {
|
||||
try {
|
||||
doBeforeCheck();
|
||||
WriteAction.run(() -> {
|
||||
getTestDictionaryFile().copy(this, getTestDictionaryFile().getParent(), TEMP_DIC); // to revert it back
|
||||
getTestDictionaryFile().delete(this);
|
||||
});
|
||||
doAfterCheck();
|
||||
}
|
||||
finally {
|
||||
//back to initial state
|
||||
WriteAction.run(() -> findFileByIoFile(Paths.get(getTestDictDirectory(), TEMP_DIC).toFile(), true).rename(this, TEST_DIC));
|
||||
}
|
||||
}
|
||||
|
||||
public void testAddDictionary() throws IOException, InterruptedException {
|
||||
doNewDictTest();
|
||||
}
|
||||
|
||||
public void testAddOneMoreDictionary() throws IOException, InterruptedException {
|
||||
doNewDictTest();
|
||||
}
|
||||
|
||||
public void testRemoveDictionary() throws IOException {
|
||||
doRemoveDictTest();
|
||||
}
|
||||
|
||||
public void testRemoveOneOfDictionaries() throws IOException {
|
||||
doRemoveDictTest();
|
||||
}
|
||||
|
||||
public void testAddToCustomDic() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAddAnotherToCustomDic() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRemoveFromCustomDic() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAddSeveralWords() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testModifyDict() throws IOException {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public abstract class SpellcheckerInspectionTestCase extends LightPlatformCodeIn
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String getSpellcheckerTestDataPath() {
|
||||
protected static String getSpellcheckerTestDataPath() {
|
||||
return "/spellchecker/testData/";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user