mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -63,7 +63,7 @@ public class ArtifactsGenerator {
|
||||
generators.add(initTarget);
|
||||
initTarget.add(new Property(ArtifactAntGenerationContextImpl.ARTIFACTS_TEMP_DIR_PROPERTY, BuildProperties.propertyRelativePath(BuildProperties.getProjectBaseDirProperty(), "artifactsTemp")));
|
||||
|
||||
final Artifact[] artifacts = ArtifactManager.getInstance(myProject).getArtifacts();
|
||||
final Artifact[] artifacts = ArtifactManager.getInstance(myProject).getSortedArtifacts();
|
||||
for (Artifact artifact : artifacts) {
|
||||
if (!myContext.shouldBuildIntoTempDirectory(artifact)) {
|
||||
generators.add(new CleanArtifactTarget(artifact, myContext));
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.packaging.impl.elements;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.elements.ComplexPackagingElementType;
|
||||
import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.ui.ArtifactEditorContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ModuleWithDependenciesElementType extends ComplexPackagingElementType<ModuleWithDependenciesPackagingElement> {
|
||||
public static final ModuleWithDependenciesElementType MODULE_WITH_DEPENDENCIES_TYPE = new ModuleWithDependenciesElementType();
|
||||
|
||||
public ModuleWithDependenciesElementType() {
|
||||
super("module-with-dependencies", "Module With Dependencies");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShowContentActionText() {
|
||||
return "Module with dependencies";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getCreateElementIcon() {
|
||||
return IconLoader.getIcon("/nodes/ModuleOpen.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) {
|
||||
return context.getModulesProvider().getModules().length > 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<? extends ModuleWithDependenciesPackagingElement> chooseAndCreate(@NotNull ArtifactEditorContext context,
|
||||
@NotNull Artifact artifact,
|
||||
@NotNull CompositePackagingElement<?> parent) {
|
||||
final List<Module> modules = ModuleOutputElementType.chooseModules(context);
|
||||
final List<ModuleWithDependenciesPackagingElement> elements = new ArrayList<ModuleWithDependenciesPackagingElement>();
|
||||
for (Module module : modules) {
|
||||
elements.add(new ModuleWithDependenciesPackagingElement(module.getName()));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ModuleWithDependenciesPackagingElement createEmpty(@NotNull Project project) {
|
||||
return new ModuleWithDependenciesPackagingElement();
|
||||
}
|
||||
}
|
||||
-127
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.packaging.impl.elements;
|
||||
|
||||
import com.intellij.openapi.compiler.CompilerBundle;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.packaging.elements.ComplexPackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElementFactory;
|
||||
import com.intellij.packaging.elements.PackagingElementResolvingContext;
|
||||
import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation;
|
||||
import com.intellij.packaging.impl.ui.ModuleElementPresentation;
|
||||
import com.intellij.packaging.ui.PackagingElementPresentation;
|
||||
import com.intellij.packaging.ui.PackagingElementWeights;
|
||||
import com.intellij.packaging.ui.ArtifactEditorContext;
|
||||
import com.intellij.packaging.artifacts.ArtifactType;
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ModuleWithDependenciesPackagingElement extends ComplexPackagingElement<ModuleWithDependenciesPackagingElement> {
|
||||
private String myModuleName;
|
||||
|
||||
public ModuleWithDependenciesPackagingElement() {
|
||||
super(ModuleWithDependenciesElementType.MODULE_WITH_DEPENDENCIES_TYPE);
|
||||
}
|
||||
|
||||
public ModuleWithDependenciesPackagingElement(String moduleName) {
|
||||
super(ModuleWithDependenciesElementType.MODULE_WITH_DEPENDENCIES_TYPE);
|
||||
myModuleName = moduleName;
|
||||
}
|
||||
|
||||
public List<? extends PackagingElement<?>> getSubstitution(@NotNull PackagingElementResolvingContext context, @NotNull ArtifactType artifactType) {
|
||||
final Module module = findModule(context);
|
||||
|
||||
List<PackagingElement<?>> elements = new ArrayList<PackagingElement<?>>();
|
||||
final PackagingElementFactory factory = PackagingElementFactory.getInstance();
|
||||
if (module != null) {
|
||||
final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module);
|
||||
for (OrderEntry entry : rootModel.getOrderEntries()) {
|
||||
if (entry instanceof ModuleSourceOrderEntry) {
|
||||
elements.add(factory.createModuleOutput(myModuleName, context.getProject()));
|
||||
}
|
||||
else if (entry instanceof LibraryOrderEntry) {
|
||||
final Library library = ((LibraryOrderEntry)entry).getLibrary();
|
||||
if (library != null) {
|
||||
elements.addAll(factory.createLibraryElements(library));
|
||||
}
|
||||
}
|
||||
else if (entry instanceof ModuleOrderEntry) {
|
||||
elements.add(new ModuleWithDependenciesPackagingElement(((ModuleOrderEntry)entry).getModuleName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final List<PackagingElement<?>> substitution = new ArrayList<PackagingElement<?>>();
|
||||
for (PackagingElement<?> element : elements) {
|
||||
final String path = artifactType.getDefaultPathFor(element, context);
|
||||
if (path != null) {
|
||||
substitution.add(factory.createParentDirectories(path, element));
|
||||
}
|
||||
}
|
||||
return substitution;
|
||||
}
|
||||
|
||||
public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
|
||||
return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModuleName, findModule(context), context) {
|
||||
@Override
|
||||
protected String getNodeText() {
|
||||
return CompilerBundle.message("node.text.0.with.dependencies", getPresentableName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWeight() {
|
||||
return PackagingElementWeights.ARTIFACT - 10;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isEqualTo(@NotNull PackagingElement<?> element) {
|
||||
return element instanceof ModuleWithDependenciesPackagingElement && myModuleName != null
|
||||
&& myModuleName.equals(((ModuleWithDependenciesPackagingElement)element).getModuleName());
|
||||
}
|
||||
|
||||
public ModuleWithDependenciesPackagingElement getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void loadState(ModuleWithDependenciesPackagingElement state) {
|
||||
myModuleName = state.getModuleName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Module findModule(PackagingElementResolvingContext context) {
|
||||
return context.getModulesProvider().getModule(myModuleName);
|
||||
}
|
||||
|
||||
@Attribute("module-name")
|
||||
public String getModuleName() {
|
||||
return myModuleName;
|
||||
}
|
||||
|
||||
public void setModuleName(String moduleName) {
|
||||
myModuleName = moduleName;
|
||||
}
|
||||
}
|
||||
-1
@@ -64,7 +64,6 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory {
|
||||
private static final PackagingElementType[] STANDARD_TYPES = {
|
||||
DIRECTORY_ELEMENT_TYPE, ARCHIVE_ELEMENT_TYPE,
|
||||
LibraryElementType.LIBRARY_ELEMENT_TYPE, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE,
|
||||
//ModuleWithDependenciesElementType.MODULE_WITH_DEPENDENCIES_TYPE,
|
||||
ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ public abstract class ElementWithManifestPropertiesPanel<E extends CompositeElem
|
||||
|
||||
private void createManifest() {
|
||||
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
descriptor.setTitle("Select Directory for MANIFEST.MF file");
|
||||
descriptor.setTitle("Select Directory for META-INF/MANIFEST.MF file");
|
||||
final VirtualFile[] files = FileChooser.chooseFiles(myContext.getProject(), descriptor, ManifestFileUtil.suggestManifestFileDirectory(myElement, myContext, myContext.getArtifactType()));
|
||||
if (files.length != 1) return;
|
||||
|
||||
|
||||
@@ -60,11 +60,6 @@ public abstract class ArtifactType {
|
||||
return getDefaultPathFor(sourceItem.getKindOfProducedElements());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDefaultPathFor(@NotNull PackagingElement<?> element, @NotNull PackagingElementResolvingContext context) {
|
||||
return getDefaultPathFor(element.getFilesKind(context));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract String getDefaultPathFor(@NotNull PackagingElementOutputKind kind);
|
||||
|
||||
|
||||
+4
@@ -64,6 +64,10 @@ public class ArtifactSourceItem extends PackagingSourceItem {
|
||||
return myArtifact.getArtifactType() instanceof JarArtifactType ? PackagingElementOutputKind.JAR_FILES : PackagingElementOutputKind.OTHER;
|
||||
}
|
||||
|
||||
public Artifact getArtifact() {
|
||||
return myArtifact;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myArtifact.hashCode();
|
||||
}
|
||||
|
||||
+10
-9
@@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -25,7 +26,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
private Set<ProjectStructureElement> myElementWithNotCalculatedUsages = new HashSet<ProjectStructureElement>();
|
||||
private MergingUpdateQueue myAnalyzerQueue;
|
||||
private List<Runnable> myListeners = new ArrayList<Runnable>();
|
||||
private boolean myStopped;
|
||||
private final AtomicBoolean myStopped = new AtomicBoolean(false);
|
||||
|
||||
public ProjectStructureDaemonAnalyzer(StructureConfigurableContext context) {
|
||||
Disposer.register(context, this);
|
||||
@@ -33,7 +34,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
}
|
||||
|
||||
private void doUpdate(final ProjectStructureElement element, final boolean check, final boolean collectUsages) {
|
||||
if (myStopped) return;
|
||||
if (myStopped.get()) return;
|
||||
|
||||
if (check) {
|
||||
doCheck(element);
|
||||
@@ -47,7 +48,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
final ProjectStructureProblemsHolder problemsHolder = new ProjectStructureProblemsHolder();
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
if (myStopped) return;
|
||||
if (myStopped.get()) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("checking " + element);
|
||||
@@ -57,7 +58,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
}.execute();
|
||||
invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (myStopped) return;
|
||||
if (myStopped.get()) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("updating problems for " + element);
|
||||
@@ -78,7 +79,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
private void doCollectUsages(final ProjectStructureElement element) {
|
||||
final List<ProjectStructureElementUsage> usages = new ReadAction<List<ProjectStructureElementUsage>>() {
|
||||
protected void run(final Result<List<ProjectStructureElementUsage>> result) {
|
||||
if (myStopped) return;
|
||||
if (myStopped.get()) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("collecting usages in " + element);
|
||||
@@ -89,7 +90,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
|
||||
invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (myStopped) return;
|
||||
if (myStopped.get()) return;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("updating usages for " + element);
|
||||
@@ -166,7 +167,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
|
||||
public void stop() {
|
||||
LOG.debug("analyzer stopped");
|
||||
myStopped = true;
|
||||
myStopped.set(true);
|
||||
myAnalyzerQueue.cancelAllUpdates();
|
||||
clearCaches();
|
||||
myAnalyzerQueue.deactivate();
|
||||
@@ -183,7 +184,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myStopped = true;
|
||||
myStopped.set(true);
|
||||
myAnalyzerQueue.cancelAllUpdates();
|
||||
}
|
||||
|
||||
@@ -211,7 +212,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
myAnalyzerQueue.activate();
|
||||
myAnalyzerQueue.queue(new Update("reset") {
|
||||
public void run() {
|
||||
myStopped = false;
|
||||
myStopped.set(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,10 +55,6 @@ public class ConfigFileFactoryImpl extends ConfigFileFactory {
|
||||
return new ConfigFileContainerImpl(project, metaDataProvider, (ConfigFileInfoSetImpl)configuration);
|
||||
}
|
||||
|
||||
public CustomConfigFileSet createCustomConfigFileSet() {
|
||||
return new CustomConfigFileSetImpl();
|
||||
}
|
||||
|
||||
private static String getText(final String templateName) throws IOException {
|
||||
final FileTemplateManager templateManager = FileTemplateManager.getInstance();
|
||||
final FileTemplate template = templateManager.getJ2eeTemplate(templateName);
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.util.descriptors.impl;
|
||||
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.descriptors.CustomConfigFile;
|
||||
import com.intellij.util.descriptors.CustomConfigFileSet;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class CustomConfigFileSetImpl implements CustomConfigFileSet {
|
||||
@NonNls private static final String ELEMENT_NAME = "deploymentDescriptor";
|
||||
@NonNls private static final String URL_ATTRIBUTE = "url";
|
||||
@NonNls private static final String OPTION_ELEMENT_NAME = "option";
|
||||
@NonNls private static final String DEFAULT_DIR_OPTION = "DEFAULT_DIR";
|
||||
@NonNls private static final String NAME_ATTRIBUTE = "name";
|
||||
@NonNls private static final String VALUE_ATTRIBUTE = "value";
|
||||
|
||||
private final List<CustomConfigFile> myDescriptors = new ArrayList<CustomConfigFile>();
|
||||
|
||||
public void add(CustomConfigFile descriptor) {
|
||||
myDescriptors.add(descriptor);
|
||||
}
|
||||
|
||||
public void remove(CustomConfigFile descriptor) {
|
||||
myDescriptors.remove(descriptor);
|
||||
}
|
||||
|
||||
public CustomConfigFile[] getConfigFiles() {
|
||||
return myDescriptors.toArray(new CustomConfigFile[myDescriptors.size()]);
|
||||
}
|
||||
|
||||
public void setConfigFiles(final Collection<CustomConfigFile> descriptors) {
|
||||
myDescriptors.clear();
|
||||
myDescriptors.addAll(descriptors);
|
||||
}
|
||||
|
||||
public void readExternal(Element element) {
|
||||
doReadExternal(element, new ArrayList<Element>());
|
||||
}
|
||||
|
||||
public void doReadExternal(Element element, List<Element> descriptorElements) {
|
||||
myDescriptors.clear();
|
||||
List<Element> descriptors = element.getChildren(ELEMENT_NAME);
|
||||
for (Element descriptor : descriptors) {
|
||||
String url = descriptor.getAttributeValue(URL_ATTRIBUTE);
|
||||
String directory = getDefaultDirOption(descriptor);
|
||||
if (directory != null) {
|
||||
myDescriptors.add(new CustomConfigFile(url, directory));
|
||||
descriptorElements.add(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getDefaultDirOption(final Element descriptor) {
|
||||
List<Element> options = descriptor.getChildren(OPTION_ELEMENT_NAME);
|
||||
for (Element option : options) {
|
||||
if (DEFAULT_DIR_OPTION.equals(option.getAttributeValue(NAME_ATTRIBUTE))) {
|
||||
return option.getAttributeValue(VALUE_ATTRIBUTE);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
for (CustomConfigFile descriptor : myDescriptors) {
|
||||
final Element child = new Element(ELEMENT_NAME);
|
||||
child.setAttribute(URL_ATTRIBUTE, descriptor.getUrl());
|
||||
final Element option = new Element(OPTION_ELEMENT_NAME);
|
||||
option.setAttribute(NAME_ATTRIBUTE, DEFAULT_DIR_OPTION);
|
||||
option.setAttribute(VALUE_ATTRIBUTE, descriptor.getOutputDirectoryPath());
|
||||
child.addContent(option);
|
||||
element.addContent(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,8 +66,7 @@ public abstract class CreateTemplateInPackageAction<T extends PsiElement> extend
|
||||
}
|
||||
});
|
||||
if (createdElement != null) {
|
||||
final PsiElement navigationElement = getNavigationElement(createdElement);
|
||||
view.selectElement(navigationElement == null ? createdElement : navigationElement);
|
||||
view.selectElement(createdElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ public abstract class ConfigFileFactory {
|
||||
|
||||
public abstract ConfigFileMetaDataRegistry createMetaDataRegistry();
|
||||
|
||||
public abstract CustomConfigFileSet createCustomConfigFileSet();
|
||||
|
||||
@Nullable
|
||||
public abstract VirtualFile createFile(@Nullable Project project, String url, ConfigFileVersion version, final boolean forceNew);
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.util.descriptors;
|
||||
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*
|
||||
* todo[nik] delete
|
||||
*/
|
||||
public interface CustomConfigFileSet extends JDOMExternalizable {
|
||||
|
||||
void add(CustomConfigFile descriptor);
|
||||
|
||||
void remove(CustomConfigFile descriptor);
|
||||
|
||||
CustomConfigFile[] getConfigFiles();
|
||||
|
||||
void setConfigFiles(Collection<CustomConfigFile> descriptors);
|
||||
}
|
||||
+8
-2
@@ -19,8 +19,10 @@ import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.KeyedExtensionCollector;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
@@ -213,8 +215,12 @@ public abstract class CompletionContributor extends AbstractCompletionContributo
|
||||
return KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(actionId));
|
||||
}
|
||||
|
||||
public static List<CompletionContributor> forParameters(CompletionParameters parameters) {
|
||||
return forLanguage(PsiUtilBase.getLanguageAtOffset(parameters.getPosition().getContainingFile(), parameters.getOffset()));
|
||||
public static List<CompletionContributor> forParameters(final CompletionParameters parameters) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<List<CompletionContributor>>() {
|
||||
public List<CompletionContributor> compute() {
|
||||
return forLanguage(PsiUtilBase.getLanguageAtOffset(parameters.getPosition().getContainingFile(), parameters.getOffset()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static List<CompletionContributor> forLanguage(Language language) {
|
||||
|
||||
@@ -1194,16 +1194,22 @@ public final class ProjectViewImpl extends ProjectView implements PersistentStat
|
||||
|
||||
private final class MyIdeView implements IdeView {
|
||||
public void selectElement(PsiElement element) {
|
||||
selectPsiElement(element, true);
|
||||
selectPsiElement(element, false);
|
||||
boolean requestFocus = true;
|
||||
if (element != null) {
|
||||
final boolean isDirectory = element instanceof PsiDirectory;
|
||||
if (!isDirectory) {
|
||||
Editor editor = EditorHelper.openInEditor(element);
|
||||
if (editor != null) {
|
||||
ToolWindowManager.getInstance(myProject).activateEditorComponent();
|
||||
requestFocus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (requestFocus) {
|
||||
selectPsiElement(element, true);
|
||||
}
|
||||
}
|
||||
|
||||
public PsiDirectory[] getDirectories() {
|
||||
|
||||
-1
@@ -266,7 +266,6 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM
|
||||
|
||||
@Override
|
||||
public void reinitComponents(Set<String> componentNames, boolean reloadData) {
|
||||
LOG.info("[STORAGE] Module: " + myModule.getName());
|
||||
super.reinitComponents(componentNames, reloadData);
|
||||
}
|
||||
|
||||
|
||||
@@ -829,7 +829,12 @@ public class AbstractTreeUi {
|
||||
boolean notRequiredToUpdateChildren = !forcedNow && !wasExpanded;
|
||||
|
||||
if (notRequiredToUpdateChildren && forceUpdate && !wasExpanded) {
|
||||
notRequiredToUpdateChildren = getBuilder().isAlwaysShowPlus(descriptor);
|
||||
boolean alwaysPlus = getBuilder().isAlwaysShowPlus(descriptor);
|
||||
if (alwaysPlus && wasLeaf) {
|
||||
notRequiredToUpdateChildren = false;
|
||||
} else {
|
||||
notRequiredToUpdateChildren = alwaysPlus;
|
||||
}
|
||||
}
|
||||
|
||||
final Ref<LoadedChildren> preloaded = new Ref<LoadedChildren>(loadedChildren);
|
||||
@@ -2956,7 +2961,9 @@ public class AbstractTreeUi {
|
||||
|
||||
|
||||
if (myTree.isExpanded(getPathFor(toExpand)) && !myUnbuiltNodes.contains(toExpand)) {
|
||||
processNodeActionsIfReady(toExpand);
|
||||
if (!areChildrenToBeUpdated(toExpand)) {
|
||||
processNodeActionsIfReady(toExpand);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!myUnbuiltNodes.contains(toExpand)) {
|
||||
@@ -2968,6 +2975,9 @@ public class AbstractTreeUi {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean areChildrenToBeUpdated(DefaultMutableTreeNode node) {
|
||||
return getUpdater().isEnqueuedToUpdate(node) || isUpdatingParent(node);
|
||||
}
|
||||
|
||||
private String asString(DefaultMutableTreeNode node) {
|
||||
if (node == null) return null;
|
||||
|
||||
@@ -316,4 +316,13 @@ public class AbstractTreeUpdater implements Disposable, Activatable {
|
||||
public void flush() {
|
||||
myUpdateQueue.sendFlush();
|
||||
}
|
||||
|
||||
public boolean isEnqueuedToUpdate(DefaultMutableTreeNode node) {
|
||||
Iterator<TreeUpdatePass> nodes = myNodeQueue.iterator();
|
||||
while (nodes.hasNext()) {
|
||||
TreeUpdatePass each = nodes.next();
|
||||
if (each.willUpdate(node)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,4 +79,9 @@ public class TreeUpdatePass {
|
||||
public String toString() {
|
||||
return "TreUpdatePass node=" + myNode + " stamp=" + myUpdateStamp + " expired=" + myExpired + " currentNode=" + myCurrentNode + " allocation=" + myAllocation;
|
||||
}
|
||||
|
||||
public boolean willUpdate(@NotNull DefaultMutableTreeNode node) {
|
||||
@NotNull DefaultMutableTreeNode currentNode = myCurrentNode != null ? myCurrentNode : myNode;
|
||||
return node.isNodeAncestor(currentNode);
|
||||
}
|
||||
}
|
||||
-1
@@ -497,7 +497,6 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
for (String componentName : componentNames) {
|
||||
final PersistentStateComponent component = (PersistentStateComponent)myComponents.get(componentName);
|
||||
if (component != null) {
|
||||
LOG.info("[STORAGE] Reinit component '" + componentName + "'");
|
||||
initPersistentComponent(component, reloadData);
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -93,7 +93,6 @@ public class FileBasedStorage extends XmlElementStorage {
|
||||
final Listener listener = messageBus.syncPublisher(STORAGE_TOPIC);
|
||||
virtualFileTracker.addTracker(fileUrl, new VirtualFileAdapter() {
|
||||
public void contentsChanged(final VirtualFileEvent event) {
|
||||
LOG.info("[STORAGE] Changed: " + myFilePath);
|
||||
listener.storageFileChanged(event, FileBasedStorage.this);
|
||||
}
|
||||
}, false, this);
|
||||
|
||||
-4
@@ -624,14 +624,11 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
|
||||
final Set<String> componentNames;
|
||||
try {
|
||||
componentNames = saveSession.analyzeExternalChanges(changedFiles);
|
||||
LOG.info("[STORAGE] Changes affects: " + (componentNames == null ? "[NONE]" :
|
||||
StringUtil.join(componentNames.toArray(new String[componentNames.size()]), ", ")));
|
||||
if (componentNames == null) return false;
|
||||
|
||||
// TODO[mike]: This is a hack to prevent NPE (assert != null) in StateStorageManagerImpl.reload, storage is null for...
|
||||
for (Pair<VirtualFile, StateStorage> pair : changedFiles) {
|
||||
if (pair.second == null) {
|
||||
LOG.info("[STORAGE] Soft reload is not possible: no state for:" + pair.first.getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -641,7 +638,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
|
||||
}
|
||||
|
||||
if (!isReloadPossible(componentNames)) {
|
||||
LOG.info("[STORAGE] Soft reload is not possible for some components :(");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -23,6 +23,7 @@ import com.intellij.openapi.options.StreamProvider;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -267,6 +268,11 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
|
||||
return null;
|
||||
}
|
||||
|
||||
final String extension = FileUtil.getExtension(new File(expandedFile).getName());
|
||||
if (extension.length() == 0) {
|
||||
throw new IllegalArgumentException("Extension is missing for storage file: " + expandedFile);
|
||||
}
|
||||
|
||||
return createFileStateStorage(fileSpec, expandedFile, myRootTagName, myPicoContainer);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,9 +116,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() {
|
||||
public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) {
|
||||
VirtualFile file = event.getFile();
|
||||
LOG.info("[STORAGE] Check if application reload is required for: " + file.getPath());
|
||||
if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) {
|
||||
LOG.info("[STORAGE] Scheduling application reload triggered by change in: " + file.getPath());
|
||||
saveChangedProjectFile(file, null, storage);
|
||||
}
|
||||
}
|
||||
@@ -133,9 +131,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() {
|
||||
public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) {
|
||||
VirtualFile file = event.getFile();
|
||||
LOG.info("[STORAGE] Check if project reload is required for: " + file.getPath());
|
||||
if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) {
|
||||
LOG.info("[STORAGE] Scheduling project reload triggered by change in: " + file.getPath());
|
||||
saveChangedProjectFile(file, project, storage);
|
||||
}
|
||||
}
|
||||
@@ -575,7 +571,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
}
|
||||
|
||||
private void askToReloadProjectIfConfigFilesChangedExternally() {
|
||||
LOG.info("[STORAGE] trying to reload project while myReloadBlockCount = " + myReloadBlockCount);
|
||||
if (myReloadBlockCount.get() == 0) {
|
||||
Set<Project> projects;
|
||||
|
||||
@@ -584,8 +579,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
projects = new HashSet<Project>(myChangedProjectFiles.keySet());
|
||||
}
|
||||
|
||||
LOG.info("[STORAGE] iterate over opened project & reload");
|
||||
|
||||
List<Project> projectsToReload = new ArrayList<Project>();
|
||||
|
||||
for (Project project : projects) {
|
||||
@@ -661,8 +654,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
if (project.isDisposed()) return false;
|
||||
final HashSet<Pair<VirtualFile, StateStorage>> causes = new HashSet<Pair<VirtualFile, StateStorage>>();
|
||||
|
||||
LOG.info("[STORAGE] Should reload project now");
|
||||
|
||||
synchronized (myChangedProjectFiles) {
|
||||
final List<Pair<VirtualFile, StateStorage>> changes = myChangedProjectFiles.remove(project);
|
||||
if (changes != null) {
|
||||
@@ -677,7 +668,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
LOG.info("[STORAGE] Checking if we could reinit components w/o project reload...");
|
||||
reloadOk[0] = ((ProjectEx)project).getStateStore().reload(causes);
|
||||
}
|
||||
catch (StateStorage.StateStorageException e) {
|
||||
@@ -692,8 +682,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
});
|
||||
if (reloadOk[0]) return false;
|
||||
|
||||
LOG.info("[STORAGE] Unable to reinit components, scheduling full project reload...");
|
||||
|
||||
String message;
|
||||
if (causes.size() == 1) {
|
||||
message = ProjectBundle.message("project.reload.external.change.single", causes.iterator().next().first.getPresentableUrl());
|
||||
@@ -730,13 +718,9 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
}
|
||||
|
||||
private void scheduleReloadApplicationAndProject() {
|
||||
LOG.info("[STORAGE] Scheduling reload with myReloadBlockCount = " + myReloadBlockCount);
|
||||
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
LOG.info("[STORAGE] trying reloading application and should reload project");
|
||||
if (!tryToReloadApplication()) return;
|
||||
LOG.info("[STORAGE] reloading project");
|
||||
askToReloadProjectIfConfigFilesChangedExternally();
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -21,7 +21,6 @@ import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.impl.win32.Win32Kernel;
|
||||
@@ -125,9 +124,7 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap
|
||||
}
|
||||
|
||||
public void disposeComponent() {
|
||||
if (SystemInfo.isWindows && Registry.is("filesystem.useNative")) {
|
||||
Win32Kernel.release();
|
||||
}
|
||||
Win32Kernel.release();
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
|
||||
@@ -34,31 +34,47 @@ import java.util.Map;
|
||||
*/
|
||||
public class Win32Kernel {
|
||||
|
||||
private static Kernel32 myKernel = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class, new HashMap<Object, Object>() {
|
||||
{
|
||||
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
|
||||
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
|
||||
}});
|
||||
private static Kernel32 ourKernel;
|
||||
|
||||
private static final int MAX_PATH = 0x00000104;
|
||||
public static final int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
|
||||
public static final int FILE_ATTRIBUTE_READONLY = 0x0001;
|
||||
|
||||
private synchronized static Kernel32 getKernel() {
|
||||
if (ourKernel == null) {
|
||||
ourKernel = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class, new HashMap<Object, Object>() {
|
||||
{
|
||||
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
|
||||
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
|
||||
}});
|
||||
WIN32_FIND_DATA.INSTANCE = new WIN32_FIND_DATA();
|
||||
BY_HANDLE_FILE_INFORMATION.INSTANCE = new BY_HANDLE_FILE_INFORMATION();
|
||||
}
|
||||
return ourKernel;
|
||||
}
|
||||
|
||||
private static class FileInfo {
|
||||
private FileInfo(WIN32_FIND_DATA data) {
|
||||
this.dwFileAttributes = data.dwFileAttributes;
|
||||
this.ftLastWriteTime = data.ftLastWriteTime.toLong();
|
||||
}
|
||||
|
||||
private FileInfo(BY_HANDLE_FILE_INFORMATION information) {
|
||||
this.dwFileAttributes = information.dwFileAttributes;
|
||||
this.ftLastWriteTime = information.ftLastWriteTime.toLong();
|
||||
}
|
||||
|
||||
int dwFileAttributes;
|
||||
long ftLastWriteTime;
|
||||
}
|
||||
|
||||
private static W32API.HANDLE INVALID_HANDLE_VALUE = new W32API.HANDLE(Pointer.createConstant(0xFFFFFFFFl));
|
||||
private static WIN32_FIND_DATA DATA = new WIN32_FIND_DATA();
|
||||
|
||||
public static void release() {
|
||||
DATA = null;
|
||||
if (ourKernel != null) {
|
||||
WIN32_FIND_DATA.INSTANCE = null;
|
||||
BY_HANDLE_FILE_INFORMATION.INSTANCE = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, FileInfo> myCache = new HashMap<String, FileInfo>();
|
||||
@@ -68,22 +84,27 @@ public class Win32Kernel {
|
||||
myCache.clear();
|
||||
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
W32API.HANDLE hFind = myKernel.FindFirstFile(absolutePath.replace('/', '\\') + "\\*", DATA);
|
||||
W32API.HANDLE hFind = getKernel().FindFirstFile(absolutePath.replace('/', '\\') + "\\*", WIN32_FIND_DATA.INSTANCE);
|
||||
if (hFind.equals(INVALID_HANDLE_VALUE)) return new String[0];
|
||||
do {
|
||||
String name = toString(DATA.cFileName);
|
||||
if (name.equals(".") || name.equals("..")) {
|
||||
String name = Native.toString(WIN32_FIND_DATA.INSTANCE.cFileName);
|
||||
if (name.equals(".")) {
|
||||
myCache.put(absolutePath, new FileInfo(WIN32_FIND_DATA.INSTANCE));
|
||||
continue;
|
||||
}
|
||||
myCache.put(absolutePath + "/" + name, new FileInfo(DATA));
|
||||
else if (name.equals("..")) {
|
||||
continue;
|
||||
}
|
||||
myCache.put(absolutePath + "/" + name, new FileInfo(WIN32_FIND_DATA.INSTANCE));
|
||||
list.add(name);
|
||||
}
|
||||
while (myKernel.FindNextFile(hFind, DATA));
|
||||
myKernel.FindClose(hFind);
|
||||
while (getKernel().FindNextFile(hFind, WIN32_FIND_DATA.INSTANCE));
|
||||
getKernel().FindClose(hFind);
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
public boolean exists(String path) {
|
||||
myCache.clear();
|
||||
try {
|
||||
getData(path);
|
||||
return true;
|
||||
@@ -110,42 +131,38 @@ public class Win32Kernel {
|
||||
FileInfo data = myCache.get(path);
|
||||
if (data == null) {
|
||||
myCache.clear();
|
||||
W32API.HANDLE hFind = myKernel.FindFirstFile(path.replace('/', '\\'), DATA);
|
||||
if (hFind.equals(INVALID_HANDLE_VALUE)) throw new FileNotFoundException(path);
|
||||
data = new FileInfo(DATA);
|
||||
myKernel.FindClose(hFind);
|
||||
if (!getKernel().GetFileAttributesEx(path.replace('/', '\\'), 0, BY_HANDLE_FILE_INFORMATION.INSTANCE)) {
|
||||
throw new FileNotFoundException(path);
|
||||
}
|
||||
data = new FileInfo(BY_HANDLE_FILE_INFORMATION.INSTANCE);
|
||||
myCache.put(path, data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private static String toString(char[] array) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] == 0) return new String(array, 0, i);
|
||||
}
|
||||
return new String(array);
|
||||
}
|
||||
|
||||
public interface Kernel32 extends StdCallLibrary {
|
||||
|
||||
W32API.HANDLE FindFirstFile(String lpFileName, WIN32_FIND_DATA lpFindFileData);
|
||||
|
||||
boolean GetFileAttributesEx(String lpFileName, int level, BY_HANDLE_FILE_INFORMATION lpFileInformation);
|
||||
|
||||
boolean FindNextFile(W32API.HANDLE hFindFile, WIN32_FIND_DATA lpFindFileData);
|
||||
|
||||
boolean FindClose(W32API.HANDLE hFindFile);
|
||||
}
|
||||
|
||||
public static class FILETIME extends Structure implements Structure.ByValue {
|
||||
|
||||
|
||||
public int dwLowDateTime;
|
||||
public int dwHighDateTime;
|
||||
|
||||
private static long l(int i) {
|
||||
if (i >= 0) {
|
||||
return i;
|
||||
} else {
|
||||
return ((long) i & 0x7FFFFFFFl) + 0x80000000l;
|
||||
}
|
||||
if (i >= 0) {
|
||||
return i;
|
||||
}
|
||||
else {
|
||||
return ((long)i & 0x7FFFFFFFl) + 0x80000000l;
|
||||
}
|
||||
}
|
||||
|
||||
public long toLong() {
|
||||
@@ -156,6 +173,8 @@ public class Win32Kernel {
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public static class WIN32_FIND_DATA extends Structure {
|
||||
|
||||
public static WIN32_FIND_DATA INSTANCE;
|
||||
|
||||
public int dwFileAttributes;
|
||||
|
||||
public FILETIME ftCreationTime;
|
||||
@@ -169,11 +188,24 @@ public class Win32Kernel {
|
||||
public int nFileSizeLow;
|
||||
|
||||
public int dwReserved0;
|
||||
|
||||
|
||||
public int dwReserved1;
|
||||
|
||||
public char[] cFileName = new char[MAX_PATH];
|
||||
|
||||
public char[] cAlternateFileName = new char[14];
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public static class BY_HANDLE_FILE_INFORMATION extends Structure {
|
||||
|
||||
public static BY_HANDLE_FILE_INFORMATION INSTANCE;
|
||||
|
||||
public int dwFileAttributes;
|
||||
public FILETIME ftCreationTime;
|
||||
public FILETIME ftLastAccessTime;
|
||||
public FILETIME ftLastWriteTime;
|
||||
public int nFileSizeHigh;
|
||||
public int nFileSizeLow;
|
||||
}
|
||||
}
|
||||
|
||||
+24
-9
@@ -33,19 +33,33 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
|
||||
@Override
|
||||
public String[] list(VirtualFile file) {
|
||||
try {
|
||||
return myKernel.list(file.getPath());
|
||||
String[] strings = myKernel.list(file.getPath());
|
||||
//assert Arrays.asList(strings).equals(Arrays.asList(super.list(file)));
|
||||
return strings;
|
||||
}
|
||||
catch (Exception e) {
|
||||
// assert false;
|
||||
return super.list(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(VirtualFile fileOrDirectory) {
|
||||
if (fileOrDirectory.getParent() == null) return true;
|
||||
boolean b = myKernel.exists(fileOrDirectory.getPath());
|
||||
//assert b == super.exists(fileOrDirectory);
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory(VirtualFile file) {
|
||||
try {
|
||||
return myKernel.isDirectory(file.getPath());
|
||||
boolean b = myKernel.isDirectory(file.getPath());
|
||||
//assert b == super.isDirectory(file);
|
||||
return b;
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
// assert false;
|
||||
return super.isDirectory(file);
|
||||
}
|
||||
}
|
||||
@@ -53,9 +67,12 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
|
||||
@Override
|
||||
public boolean isWritable(VirtualFile file) {
|
||||
try {
|
||||
return myKernel.isWritable(file.getPath());
|
||||
boolean b = myKernel.isWritable(file.getPath());
|
||||
//assert b == super.isWritable(file);
|
||||
return b;
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
// assert false: file;
|
||||
return super.isWritable(file);
|
||||
}
|
||||
}
|
||||
@@ -63,18 +80,16 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
|
||||
@Override
|
||||
public long getTimeStamp(VirtualFile file) {
|
||||
try {
|
||||
return myKernel.getTimeStamp(file.getPath());
|
||||
long timeStamp = myKernel.getTimeStamp(file.getPath());
|
||||
//assert timeStamp == super.getTimeStamp(file);
|
||||
return timeStamp;
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
// assert false;
|
||||
return super.getTimeStamp(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(VirtualFile fileOrDirectory) {
|
||||
return myKernel.exists(fileOrDirectory.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WatchRequest addRootToWatch(@NotNull String rootPath, boolean toWatchRecursively) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.vfs.newvfs.persistent;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -58,7 +59,7 @@ public class RefreshWorker {
|
||||
}
|
||||
else {
|
||||
if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) && SystemInfo.isWindows && root.isDirectory() &&
|
||||
(Registry.is("filesystem.useNative"))) {
|
||||
(!ApplicationManager.getApplication().isUnitTestMode() && Registry.is("filesystem.useNative"))) {
|
||||
delegate = new Win32LocalFileSystem();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ actionSystem.playback.description=Delay between events generated by the playback
|
||||
actionSystem.focusIdleTimeout=20
|
||||
actionSystem.mac.screenMenuNotUpdatedFix=false
|
||||
actionSystem.keyGestures.enabled=false
|
||||
actionSystem.suspendFocusTransferIfApplicationInactive=true
|
||||
actionSystem.suspendFocusTransferIfApplicationInactive=false
|
||||
|
||||
ide.debugMode=true
|
||||
ide.debugMode.description=Record additonal information to make bug reports more informative
|
||||
@@ -39,4 +39,4 @@ ide.tabbedPane.bufferedPaint=true
|
||||
debugger.valueTooltipAutoShow=true
|
||||
debugger.valueTooltipAutoShow.description=Auto show tooltip on mouse over
|
||||
|
||||
filesystem.useNative=false
|
||||
filesystem.useNative=true
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.intellij.ui;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.plaf.basic.BasicRadioButtonUI;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public class CheckBoxList extends JList {
|
||||
private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
|
||||
private static final int DEFAULT_CHECK_BOX_WIDTH = 20;
|
||||
|
||||
public CheckBoxList(final ListModel dataModel, final CheckBoxListListener checkBoxListListener) {
|
||||
super(dataModel);
|
||||
setCellRenderer(new CellRenderer());
|
||||
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
setBorder(BorderFactory.createEtchedBorder());
|
||||
addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
if (e.getKeyChar() == ' ') {
|
||||
int index = CheckBoxList.this.getSelectedIndex();
|
||||
|
||||
if (index >= 0) {
|
||||
JCheckBox checkbox = (JCheckBox)getModel().getElementAt(index);
|
||||
setSelected(checkbox, index, checkBoxListListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (isEnabled()) {
|
||||
int index = locationToIndex(e.getPoint());
|
||||
|
||||
if (index != -1) {
|
||||
JCheckBox checkbox = (JCheckBox)getModel().getElementAt(index);
|
||||
int iconArea;
|
||||
try {
|
||||
iconArea = ((BasicRadioButtonUI)checkbox.getUI()).getDefaultIcon().getIconWidth();
|
||||
}
|
||||
catch (ClassCastException c) {
|
||||
iconArea = DEFAULT_CHECK_BOX_WIDTH;
|
||||
}
|
||||
if (e.getX() < iconArea) {
|
||||
setSelected(checkbox, index, checkBoxListListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setSelected(JCheckBox checkbox, int index, CheckBoxListListener checkBoxListListener) {
|
||||
boolean value = !checkbox.isSelected();
|
||||
checkbox.setSelected(value);
|
||||
repaint();
|
||||
checkBoxListListener.checkBoxSelectionChanged(index, value);
|
||||
}
|
||||
|
||||
private class CellRenderer implements ListCellRenderer {
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JCheckBox checkbox = (JCheckBox)value;
|
||||
checkbox.setBackground(getBackgound(isSelected, checkbox));
|
||||
checkbox.setForeground(getForeGround(isSelected, checkbox));
|
||||
checkbox.setEnabled(isEnabled());
|
||||
checkbox.setFont(getFont(checkbox));
|
||||
checkbox.setFocusPainted(false);
|
||||
checkbox.setBorderPainted(true);
|
||||
checkbox.setBorder(isSelected ? UIManager.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
|
||||
return checkbox;
|
||||
}
|
||||
}
|
||||
|
||||
protected Font getFont(final JCheckBox checkbox) {
|
||||
return getFont();
|
||||
}
|
||||
|
||||
protected Color getBackgound(final boolean isSelected, final JCheckBox checkbox) {
|
||||
return isSelected ? getSelectionBackground() : getBackground();
|
||||
}
|
||||
|
||||
protected Color getForeGround(final boolean isSelected, final JCheckBox checkbox) {
|
||||
return isSelected ? getSelectionForeground() : getForeground();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.intellij.ui;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public interface CheckBoxListListener {
|
||||
void checkBoxSelectionChanged(int index, boolean value);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ui.OptionalChooserComponent">
|
||||
<grid id="27dc6" binding="myContentPane" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="10" left="7" bottom="7" right="7"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="455" height="247"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<scrollpane id="4c4f5">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="1e69c" class="com.intellij.ui.CheckBoxList" binding="myList" custom-create="true">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<selectionMode value="0"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.intellij.ui;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
* This component represents a list of checkboxes.
|
||||
*/
|
||||
public abstract class OptionalChooserComponent implements CheckBoxListListener {
|
||||
private JPanel myContentPane;
|
||||
private CheckBoxList myList;
|
||||
private DefaultListModel myListModel;
|
||||
private List<Pair<String, Boolean>> myInitialList;
|
||||
private ArrayList<Pair<String, Boolean>> myWorkingList;
|
||||
|
||||
public OptionalChooserComponent(@NotNull final List<Pair<String, Boolean>> list) {
|
||||
myInitialList = list;
|
||||
myWorkingList = new ArrayList<Pair<String, Boolean>>(myInitialList);
|
||||
|
||||
// fill list
|
||||
reset();
|
||||
}
|
||||
|
||||
public JPanel getContentPane() {
|
||||
return myContentPane;
|
||||
}
|
||||
|
||||
public void checkBoxSelectionChanged(int index, boolean value) {
|
||||
final Pair<String, Boolean> pair = myWorkingList.remove(index);
|
||||
myWorkingList.add(index, Pair.create(pair.first, value));
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
myListModel = new DefaultListModel();
|
||||
myList = new CheckBoxList(myListModel, this);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
myWorkingList = new ArrayList<Pair<String, Boolean>>(myInitialList);
|
||||
update();
|
||||
}
|
||||
|
||||
public abstract JCheckBox createCheckBox(final String path, final boolean checked);
|
||||
|
||||
public boolean isModified() {
|
||||
return !myWorkingList.equals(myInitialList);
|
||||
}
|
||||
|
||||
public ArrayList<Pair<String, Boolean>> getValue() {
|
||||
return myWorkingList;
|
||||
}
|
||||
|
||||
public void apply() {
|
||||
myInitialList.clear();
|
||||
myInitialList.addAll(myWorkingList);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
myListModel.clear();
|
||||
for (Pair<String, Boolean> pair : myWorkingList) {
|
||||
myListModel.addElement(createCheckBox(pair.first, pair.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ui.PathsChooserComponent">
|
||||
<grid id="27dc6" binding="myContentPane" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="10" left="7" bottom="7" right="7"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="591" height="247"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<vspacer id="e6d11">
|
||||
<constraints>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<scrollpane id="837a">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="3" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="8b3da" class="javax.swing.JList" binding="myList">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<selectionMode value="0"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
<component id="360f6" class="javax.swing.JButton" binding="myAddButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/UIBundle" key="row.add"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="f80a3" class="javax.swing.JButton" binding="myRemoveButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/UIBundle" key="row.remove"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.intellij.ui;
|
||||
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDialog;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
* This component is used to configure list of folders with add/remove buttons.
|
||||
*/
|
||||
public class PathsChooserComponent {
|
||||
private JPanel myContentPane;
|
||||
private JList myList;
|
||||
private JButton myAddButton;
|
||||
private JButton myRemoveButton;
|
||||
private DefaultListModel myListModel;
|
||||
|
||||
private List<String> myWorkingCollection;
|
||||
private List<String> myInitialCollection;
|
||||
|
||||
public PathsChooserComponent(@NotNull final List<String> collection, @NotNull final PathProcessor processor) {
|
||||
myInitialCollection = collection;
|
||||
myWorkingCollection = new ArrayList<String>(myInitialCollection);
|
||||
myListModel = new DefaultListModel();
|
||||
myList.setModel(myListModel);
|
||||
|
||||
// fill list
|
||||
reset();
|
||||
|
||||
// listeners
|
||||
myAddButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final FileChooserDescriptor dirChooser = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
dirChooser.setShowFileSystemRoots(true);
|
||||
dirChooser.setHideIgnored(true);
|
||||
dirChooser.setTitle(UIBundle.message("file.chooser.default.title"));
|
||||
FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(dirChooser, myContentPane);
|
||||
VirtualFile[] files = chooser.choose(null, null);
|
||||
for (VirtualFile file : files) {
|
||||
// adding to the end
|
||||
final String path = file.getPath();
|
||||
if (processor.addPath(myWorkingCollection, path)){
|
||||
myListModel.addElement(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myRemoveButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int selected = myList.getSelectedIndex();
|
||||
if (selected != -1) {
|
||||
// removing index
|
||||
final String path = (String) myListModel.get(selected);
|
||||
if (processor.removePath(myWorkingCollection, path)){
|
||||
myListModel.remove(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public JPanel getContentPane() {
|
||||
return myContentPane;
|
||||
}
|
||||
|
||||
public List<String> getValues(){
|
||||
return myWorkingCollection;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
myListModel.clear();
|
||||
myWorkingCollection = new ArrayList<String>(myInitialCollection);
|
||||
for (String path : myWorkingCollection) {
|
||||
myListModel.addElement(path);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return !myWorkingCollection.equals(myInitialCollection);
|
||||
}
|
||||
|
||||
public void apply() {
|
||||
myInitialCollection.clear();
|
||||
myInitialCollection.addAll(myWorkingCollection);
|
||||
}
|
||||
|
||||
public interface PathProcessor {
|
||||
boolean addPath(List<String> paths, String path);
|
||||
boolean removePath(List<String> paths, String path);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
<orderEntry type="module" module-name="platform-resources-en" />
|
||||
<orderEntry type="library" name="OroMatcher" level="project" />
|
||||
<orderEntry type="module" module-name="annotations" exported="" />
|
||||
<orderEntry type="module" module-name="platform-api" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -26,6 +26,10 @@ import com.intellij.openapi.command.CommandAdapter;
|
||||
import com.intellij.openapi.command.CommandEvent;
|
||||
import com.intellij.openapi.command.CommandListener;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.roots.ModuleRootListener;
|
||||
@@ -57,6 +61,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
* shows balloon that notifies user about the problem and offers to correct root mapping.
|
||||
*/
|
||||
public class GitRootTracker implements VcsListener {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#git4idea.vfs.GitRootTracker");
|
||||
|
||||
/**
|
||||
* The context project
|
||||
*/
|
||||
@@ -169,7 +176,7 @@ public class GitRootTracker implements VcsListener {
|
||||
}
|
||||
};
|
||||
fileManager.addVirtualFileManagerListener(myVirtualFileManagerListener);
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() {
|
||||
StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() {
|
||||
public void run() {
|
||||
myIsEnabled.set(true);
|
||||
checkRoots(true);
|
||||
@@ -208,94 +215,106 @@ public class GitRootTracker implements VcsListener {
|
||||
if (!myIsEnabled.get() || (!rootsChanged && !myHasGitRoots.get())) {
|
||||
return;
|
||||
}
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
boolean hasInvalidRoots = false;
|
||||
HashSet<String> rootSet = new HashSet<String>();
|
||||
for (VcsDirectoryMapping m : myVcsManager.getDirectoryMappings()) {
|
||||
if (!m.getVcs().equals(myVcs.getName())) {
|
||||
continue;
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(myProject, "Checking unmapped Git roots...") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
LOG.info("Checking unmapped Git roots...");
|
||||
long start = System.currentTimeMillis();
|
||||
doCheck();
|
||||
LOG.info("Unmapped Git roots checked in " + (System.currentTimeMillis() - start) + "ms");
|
||||
}
|
||||
String path = m.getDirectory();
|
||||
if (path.length() == 0) {
|
||||
VirtualFile baseDir = myProject.getBaseDir();
|
||||
assert baseDir != null;
|
||||
path = baseDir.getPath();
|
||||
}
|
||||
VirtualFile root = lookupFile(path);
|
||||
if (root == null) {
|
||||
hasInvalidRoots = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
rootSet.add(root.getPath());
|
||||
}
|
||||
}
|
||||
if (!hasInvalidRoots && rootSet.isEmpty()) {
|
||||
myHasGitRoots.set(false);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
myHasGitRoots.set(true);
|
||||
}
|
||||
if (!hasInvalidRoots) {
|
||||
// check if roots have a problem
|
||||
loop:
|
||||
for (String path : rootSet) {
|
||||
VirtualFile root = lookupFile(path);
|
||||
VirtualFile gitRoot = GitUtil.gitRootOrNull(root);
|
||||
if (gitRoot == null || hasUnmappedSubroots(root, rootSet)) {
|
||||
hasInvalidRoots = true;
|
||||
break;
|
||||
}
|
||||
for (String otherPath : rootSet) {
|
||||
if (otherPath.equals(path)) {
|
||||
continue;
|
||||
}
|
||||
if (otherPath.startsWith(path)) {
|
||||
VirtualFile otherFile = lookupFile(otherPath);
|
||||
if (otherFile == null) {
|
||||
hasInvalidRoots = true;
|
||||
break loop;
|
||||
}
|
||||
VirtualFile otherRoot = GitUtil.gitRootOrNull(otherFile);
|
||||
if (otherRoot == null || otherRoot == root || otherFile != otherRoot) {
|
||||
hasInvalidRoots = true;
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasInvalidRoots) {
|
||||
// all roots are correct
|
||||
if (myNotificationPosted.compareAndSet(true, false)) {
|
||||
if (myNotification != null) {
|
||||
if (!myNotification.isExpired()) {
|
||||
myNotification.expire();
|
||||
}
|
||||
|
||||
myNotification = null;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (myNotificationPosted.compareAndSet(false, true)) {
|
||||
myNotification = new Notification(GIT_INVALID_ROOTS_ID, GitBundle.getString("root.tracker.message.title"),
|
||||
GitBundle.getString("root.tracker.message"),
|
||||
NotificationType.ERROR, new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
if (fixRoots()) {
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Notifications.Bus.notify(myNotification, myProject);
|
||||
}
|
||||
});
|
||||
myMulticaster.gitRootsChanged();
|
||||
}
|
||||
});
|
||||
myMulticaster.gitRootsChanged();
|
||||
}
|
||||
|
||||
private void doCheck() {
|
||||
boolean hasInvalidRoots = false;
|
||||
HashSet<String> rootSet = new HashSet<String>();
|
||||
for (VcsDirectoryMapping m : myVcsManager.getDirectoryMappings()) {
|
||||
if (!m.getVcs().equals(myVcs.getName())) {
|
||||
continue;
|
||||
}
|
||||
String path = m.getDirectory();
|
||||
if (path.length() == 0) {
|
||||
VirtualFile baseDir = myProject.getBaseDir();
|
||||
assert baseDir != null;
|
||||
path = baseDir.getPath();
|
||||
}
|
||||
VirtualFile root = lookupFile(path);
|
||||
if (root == null) {
|
||||
hasInvalidRoots = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
rootSet.add(root.getPath());
|
||||
}
|
||||
}
|
||||
if (!hasInvalidRoots && rootSet.isEmpty()) {
|
||||
myHasGitRoots.set(false);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
myHasGitRoots.set(true);
|
||||
}
|
||||
if (!hasInvalidRoots) {
|
||||
// check if roots have a problem
|
||||
loop:
|
||||
for (String path : rootSet) {
|
||||
VirtualFile root = lookupFile(path);
|
||||
VirtualFile gitRoot = GitUtil.gitRootOrNull(root);
|
||||
if (gitRoot == null || hasUnmappedSubroots(root, true, rootSet)) {
|
||||
hasInvalidRoots = true;
|
||||
break;
|
||||
}
|
||||
for (String otherPath : rootSet) {
|
||||
if (otherPath.equals(path)) {
|
||||
continue;
|
||||
}
|
||||
if (otherPath.startsWith(path)) {
|
||||
VirtualFile otherFile = lookupFile(otherPath);
|
||||
if (otherFile == null) {
|
||||
hasInvalidRoots = true;
|
||||
break loop;
|
||||
}
|
||||
VirtualFile otherRoot = GitUtil.gitRootOrNull(otherFile);
|
||||
if (otherRoot == null || otherRoot == root || otherFile != otherRoot) {
|
||||
hasInvalidRoots = true;
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasInvalidRoots) {
|
||||
// all roots are correct
|
||||
if (myNotificationPosted.compareAndSet(true, false)) {
|
||||
if (myNotification != null) {
|
||||
if (!myNotification.isExpired()) {
|
||||
myNotification.expire();
|
||||
}
|
||||
|
||||
myNotification = null;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (myNotificationPosted.compareAndSet(false, true)) {
|
||||
myNotification = new Notification(GIT_INVALID_ROOTS_ID, GitBundle.getString("root.tracker.message.title"),
|
||||
GitBundle.getString("root.tracker.message"),
|
||||
NotificationType.ERROR, new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
if (fixRoots()) {
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Notifications.Bus.notify(myNotification, myProject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,15 +324,14 @@ public class GitRootTracker implements VcsListener {
|
||||
* @param rootSet the mapped root set
|
||||
* @return true if there are unmapped subroots
|
||||
*/
|
||||
private static boolean hasUnmappedSubroots(VirtualFile directory, HashSet<String> rootSet) {
|
||||
private static boolean hasUnmappedSubroots(VirtualFile directory, boolean isRoot, HashSet<String> rootSet) {
|
||||
for (VirtualFile child : directory.getChildren()) {
|
||||
if (child.getName().equals(".git") || !child.isDirectory()) {
|
||||
continue;
|
||||
if (child.getName().equals(".git")) {
|
||||
if (isRoot || !child.isDirectory())
|
||||
continue;
|
||||
return !rootSet.contains(directory.getPath());
|
||||
}
|
||||
if (child.findChild(".git") != null && !rootSet.contains(child.getPath())) {
|
||||
return true;
|
||||
}
|
||||
if (hasUnmappedSubroots(child, rootSet)) {
|
||||
if (child.isDirectory() && hasUnmappedSubroots(child, false, rootSet)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.*;
|
||||
|
||||
class FilterCache {
|
||||
private final ArrayList<TestProxy> myList = new ArrayList<TestProxy>(4);
|
||||
private final Set<TestProxy> mySet = new HashSet<TestProxy>();
|
||||
private final Map<Filter, ArrayList<TestProxy>> myCache = new THashMap<Filter, ArrayList<TestProxy>>();
|
||||
|
||||
public TestProxy[] select(final Filter filter) {
|
||||
@@ -46,9 +47,14 @@ class FilterCache {
|
||||
|
||||
public void add(final TestProxy test) {
|
||||
myList.add(test);
|
||||
mySet.add(test);
|
||||
resetCache();
|
||||
}
|
||||
|
||||
public boolean contains(TestProxy test) {
|
||||
return mySet.contains(test);
|
||||
}
|
||||
|
||||
public AbstractTestProxy detect(final Filter filter) {
|
||||
return filter.detectIn(myList);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class SuiteState extends TestState {
|
||||
return myCache.get(ALL_TESTS);
|
||||
}
|
||||
|
||||
public void changeStateAfterAddingChaildTo(final TestProxy test, final TestProxy child) {
|
||||
public void changeStateAfterAddingChildTo(final TestProxy test, final TestProxy child) {
|
||||
if (child.getState().getMagnitude() <= getMagnitude()) {
|
||||
test.onStatisticsChanged();
|
||||
return;
|
||||
|
||||
@@ -102,7 +102,6 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
|
||||
pullEvent(new StateChangedEvent(this));
|
||||
if (myParent != null)
|
||||
myParent.onChanged(this);
|
||||
fireStatisticsChanged();
|
||||
myNotifier.onChanged(this);
|
||||
}
|
||||
|
||||
@@ -163,7 +162,7 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
|
||||
}
|
||||
|
||||
public void addChild(final TestProxy child) {
|
||||
if (myChildren.getList().contains(child))
|
||||
if (myChildren.contains(child))
|
||||
return;
|
||||
if (child.getParent() != null)
|
||||
return;//todo throw new RuntimeException("Test: "+child + " already has parent: " + child.getParent());
|
||||
@@ -174,8 +173,7 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
|
||||
child.fireOnNewPrintable(child);
|
||||
}
|
||||
pullEvent(new NewChildEvent(this, child));
|
||||
fireStatisticsChanged();
|
||||
getState().changeStateAfterAddingChaildTo(this, child);
|
||||
getState().changeStateAfterAddingChildTo(this, child);
|
||||
myNotifier.onChildAdded(this, child);
|
||||
}
|
||||
|
||||
@@ -203,11 +201,6 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
|
||||
}
|
||||
|
||||
public void onStatisticsChanged() {
|
||||
myChildren.resetCache();
|
||||
fireStatisticsChanged();
|
||||
}
|
||||
|
||||
private void fireStatisticsChanged() {
|
||||
myChildren.resetCache();
|
||||
if (myParent != null)
|
||||
myParent.onStatisticsChanged();
|
||||
@@ -220,12 +213,11 @@ public class TestProxy extends CompositePrintable implements PrintableTestProxy,
|
||||
}
|
||||
|
||||
public void setStatistics(final Statistics statistics) {
|
||||
myChildren.resetCache();
|
||||
if (!myState.isFinal()) {
|
||||
LOG.error("" + myState.getMagnitude());
|
||||
LOG.error(String.valueOf(myState.getMagnitude()));
|
||||
}
|
||||
myStatistics = statistics;
|
||||
fireStatisticsChanged();
|
||||
onStatisticsChanged();
|
||||
}
|
||||
|
||||
public Statistics getStatisticsImpl() {
|
||||
|
||||
@@ -65,7 +65,7 @@ public abstract class TestState implements Printable {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void changeStateAfterAddingChaildTo(final TestProxy test, final TestProxy child) {
|
||||
public void changeStateAfterAddingChildTo(final TestProxy test, final TestProxy child) {
|
||||
test.setState(new SuiteState(test));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class TestStateUpdater implements PacketConsumer {
|
||||
final List<TestProxy> children = parent.getChildren();
|
||||
final TestState parentState = parent.getState();
|
||||
LOG.assertTrue(parentState instanceof SuiteState);
|
||||
if (children.indexOf(child) == children.size() - 1) {
|
||||
if (child.equals(children.get(children.size() - 1))) {
|
||||
((SuiteState)parentState).setRunning(false);
|
||||
}
|
||||
((SuiteState)parentState).updateMagnitude(magnitude);
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.intellij.execution.junit2.ui;
|
||||
|
||||
import com.intellij.execution.junit2.NewChildEvent;
|
||||
import com.intellij.execution.junit2.StatisticsChanged;
|
||||
import com.intellij.execution.junit2.TestEvent;
|
||||
import com.intellij.execution.junit2.TestProxy;
|
||||
import com.intellij.execution.junit2.ui.actions.TestContext;
|
||||
@@ -70,9 +68,9 @@ class StatisticsPanel extends JPanel implements DataProvider{
|
||||
myTable.setVisible(true);
|
||||
// myTestCaseInfo.setVisible(false);
|
||||
if (myCurrentTest.isLeaf() && myCurrentTest.getParent() != null) {
|
||||
myChildInfo.onSelectionChanged(myCurrentTest.getParent());
|
||||
myChildInfo.updateStatistics(myCurrentTest.getParent());
|
||||
} else{
|
||||
myChildInfo.onSelectionChanged(myCurrentTest);
|
||||
myChildInfo.updateStatistics(myCurrentTest);
|
||||
}
|
||||
final int idx = myChildInfo.getIndexOf(myCurrentTest);
|
||||
TableUtil.selectRows(myTable, new int[]{idx});
|
||||
@@ -99,13 +97,7 @@ class StatisticsPanel extends JPanel implements DataProvider{
|
||||
private class MyJUnitListener extends JUnitAdapter {
|
||||
public void onTestChanged(final TestEvent event) {
|
||||
if (!StatisticsPanel.this.isShowing()) return;
|
||||
if (event instanceof StatisticsChanged) {
|
||||
if (myCurrentTest == event.getSource())
|
||||
updateStatistics();
|
||||
} else if (event instanceof NewChildEvent) {
|
||||
if (event.getSource() == myCurrentTest && !myTable.isVisible())
|
||||
updateStatistics();
|
||||
}
|
||||
if (myCurrentTest == event.getSource()) updateStatistics();
|
||||
}
|
||||
|
||||
public void onTestSelected(final TestProxy test) {
|
||||
|
||||
@@ -47,8 +47,7 @@ public class StatisticsTable extends ListTableModel {
|
||||
|
||||
private void setTest(final TestProxy test) {
|
||||
if (myTest == test) return;
|
||||
myTest = test;
|
||||
changeTableData();
|
||||
updateStatistics(test);
|
||||
}
|
||||
|
||||
private void changeTableData() {
|
||||
@@ -102,4 +101,9 @@ public class StatisticsTable extends ListTableModel {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void updateStatistics(TestProxy currentTest) {
|
||||
myTest = currentTest;
|
||||
changeTableData();
|
||||
}
|
||||
}
|
||||
|
||||
+11
-8
@@ -23,12 +23,12 @@ import com.intellij.execution.junit2.segments.DispatchListener;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class JUnitListenersNotifier implements JUnitListener, TestEventsConsumer, DispatchListener, Runnable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit2.ui.model.JUnitListenersNotifier");
|
||||
@@ -142,7 +142,7 @@ public class JUnitListenersNotifier implements JUnitListener, TestEventsConsumer
|
||||
|
||||
private void dispatchAllEvents() {
|
||||
//long start = System.currentTimeMillis();
|
||||
final List<TestEvent> filteredEvents = removeDuplicatesFromEnd(myEventsQueue);
|
||||
final List<TestEvent> filteredEvents = removeDuplicates(myEventsQueue);
|
||||
myEventsQueue.clear();
|
||||
// MEASURER.start(DISPATCH_SINGLES);
|
||||
for (final TestEvent event : filteredEvents) {
|
||||
@@ -153,11 +153,14 @@ public class JUnitListenersNotifier implements JUnitListener, TestEventsConsumer
|
||||
//System.out.println("duration = " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
|
||||
public static <T> List<T> removeDuplicatesFromEnd(final List<T> list) {
|
||||
ArrayList<T> result = new ArrayList<T>(list);
|
||||
Collections.reverse(result);
|
||||
ContainerUtil.removeDuplicates(result);
|
||||
Collections.reverse(result);
|
||||
private static <T> List<T> removeDuplicates(final List<T> list) {
|
||||
final ArrayList<T> result = new ArrayList<T>(list.size());
|
||||
final Set<T> collected = new HashSet<T>();
|
||||
for (T t : list) {
|
||||
if (collected.contains(t)) continue;
|
||||
collected.add(t);
|
||||
result.add(t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
|
||||
|
||||
<projectService serviceInterface="com.intellij.spellchecker.options.SpellCheckerConfiguration"
|
||||
serviceImplementation="com.intellij.spellchecker.options.SpellCheckerConfiguration"/>
|
||||
<projectService serviceInterface="com.intellij.spellchecker.settings.SpellCheckerSettings"
|
||||
serviceImplementation="com.intellij.spellchecker.settings.SpellCheckerSettings"/>
|
||||
<projectService serviceInterface="com.intellij.spellchecker.SpellCheckerManager"
|
||||
serviceImplementation="com.intellij.spellchecker.SpellCheckerManager"/>
|
||||
<projectConfigurable implementation="com.intellij.spellchecker.options.SpellCheckerConfigurable"/>
|
||||
<projectConfigurable implementation="com.intellij.spellchecker.settings.SpellCheckerSettingsManager"/>
|
||||
|
||||
|
||||
<inspectionToolProvider
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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;
|
||||
|
||||
import com.intellij.psi.codeStyle.NameUtil;
|
||||
import com.intellij.spellchecker.engine.SuggestionProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class BaseSuggestionProvider implements SuggestionProvider {
|
||||
|
||||
private final SpellCheckerManager manager;
|
||||
|
||||
public BaseSuggestionProvider(@NotNull SpellCheckerManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getSuggestions(@NotNull String text) {
|
||||
|
||||
String[] words = NameUtil.nameToWords(text);
|
||||
|
||||
int index = 0;
|
||||
List[] res = new List[words.length];
|
||||
int i = 0;
|
||||
for (String word : words) {
|
||||
int start = text.indexOf(word, index);
|
||||
int end = start + word.length();
|
||||
if (!manager.hasProblem(word)) {
|
||||
List<String> variants = new ArrayList<String>();
|
||||
variants.add(word);
|
||||
res[i++] = variants;
|
||||
}
|
||||
else {
|
||||
List<String> variants = manager.getRawSuggestions(word);
|
||||
res[i++] = variants;
|
||||
}
|
||||
index = end;
|
||||
}
|
||||
|
||||
String[] all = null;
|
||||
int[] counter = new int[i];
|
||||
int size = 1;
|
||||
for (int j = 0; j < i; j++) {
|
||||
size *= res[j].size();
|
||||
}
|
||||
all = new String[size];
|
||||
|
||||
for (int k = 0; k < size; k++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (all[k] == null) {
|
||||
all[k] = "";
|
||||
}
|
||||
all[k] += res[j].get(counter[j]);
|
||||
counter[j]++;
|
||||
if (counter[j] >= res[j].size()) {
|
||||
counter[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Arrays.asList(all);
|
||||
}
|
||||
}
|
||||
@@ -15,42 +15,45 @@
|
||||
*/
|
||||
package com.intellij.spellchecker;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.spellchecker.dictionary.Loader;
|
||||
import com.intellij.spellchecker.dictionary.Processor;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
public class FileLoader implements Loader {
|
||||
|
||||
private String url;
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.FileLoader");
|
||||
|
||||
public FileLoader(String url) {
|
||||
this.url = url;
|
||||
private String url;
|
||||
|
||||
public FileLoader(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void load(@NotNull Consumer<String> consumer) {
|
||||
File file = new File(url);
|
||||
FileInputStream stream = null;
|
||||
try {
|
||||
stream = new FileInputStream(file);
|
||||
StreamLoader loader = new StreamLoader(stream);
|
||||
loader.load(consumer);
|
||||
}
|
||||
|
||||
public void load(@NotNull Processor processor) {
|
||||
|
||||
InputStream io = SpellCheckerManager.class.getResourceAsStream(url);
|
||||
DataInputStream in = new DataInputStream(io);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
try{
|
||||
String strLine;
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
processor.process(strLine);
|
||||
}
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
br.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
stream.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -25,8 +25,12 @@ import com.intellij.spellchecker.dictionary.Dictionary;
|
||||
import com.intellij.spellchecker.dictionary.Loader;
|
||||
import com.intellij.spellchecker.engine.SpellCheckerEngine;
|
||||
import com.intellij.spellchecker.engine.SpellCheckerFactory;
|
||||
import com.intellij.spellchecker.engine.SuggestionProvider;
|
||||
import com.intellij.spellchecker.settings.SpellCheckerSettings;
|
||||
import com.intellij.spellchecker.state.StateLoader;
|
||||
import com.intellij.spellchecker.util.SPFileUtil;
|
||||
import com.intellij.spellchecker.util.Strings;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -43,13 +47,26 @@ public class SpellCheckerManager {
|
||||
|
||||
private Dictionary userDictionary;
|
||||
|
||||
private final String[] bundledDictionaries = new String[]{"english.dic", "jetbrains.dic"};
|
||||
|
||||
@NotNull
|
||||
private final SuggestionProvider suggestionProvider = new BaseSuggestionProvider(this);
|
||||
|
||||
private final SpellCheckerSettings settings;
|
||||
|
||||
public static SpellCheckerManager getInstance(Project project) {
|
||||
return ServiceManager.getService(project, SpellCheckerManager.class);
|
||||
}
|
||||
|
||||
public SpellCheckerManager(Project project) {
|
||||
public SpellCheckerManager(Project project, SpellCheckerSettings settings) {
|
||||
this.project = project;
|
||||
this.settings = settings;
|
||||
reloadConfiguration();
|
||||
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public Dictionary getUserDictionary() {
|
||||
@@ -64,7 +81,26 @@ public class SpellCheckerManager {
|
||||
private void fillEngineDictionary() {
|
||||
spellChecker.reset();
|
||||
final StateLoader stateLoader = new StateLoader(project);
|
||||
Loader[] loaders = new Loader[]{new FileLoader("english.dic"), new FileLoader("jetbrains.dic"), stateLoader};
|
||||
final List<Loader> loaders = new ArrayList<Loader>();
|
||||
for (String dictionary : bundledDictionaries) {
|
||||
if (this.settings == null || !this.settings.getBundledDisabledDictionariesPaths().contains(dictionary)) {
|
||||
loaders.add(new StreamLoader(SpellCheckerManager.class.getResourceAsStream(dictionary)));
|
||||
}
|
||||
}
|
||||
if (this.settings != null && this.settings.getDictionaryFoldersPaths() != null) {
|
||||
final Set<String> disabledDictionaries = settings.getDisabledDictionariesPaths();
|
||||
for (String folder : this.settings.getDictionaryFoldersPaths()) {
|
||||
SPFileUtil.processFilesRecursively(folder, new Consumer<String>() {
|
||||
public void consume(final String s) {
|
||||
if (!disabledDictionaries.contains(s)) {
|
||||
loaders.add(new FileLoader(s));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
loaders.add(stateLoader);
|
||||
for (Loader loader : loaders) {
|
||||
spellChecker.loadDictionary(loader);
|
||||
}
|
||||
@@ -84,22 +120,31 @@ public class SpellCheckerManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateUserWords(@Nullable Collection<String> words) {
|
||||
Set<String> transformed = spellChecker.getTransformation().transform(words);
|
||||
userDictionary.replaceAll(transformed);
|
||||
fillEngineDictionary();
|
||||
public void update(@Nullable Collection<String> words, SpellCheckerSettings allDictionaries) {
|
||||
reloadConfiguration();
|
||||
restartInspections();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public List<String> getBundledDictionaries() {
|
||||
return (bundledDictionaries != null ? Arrays.asList(bundledDictionaries) : Collections.<String>emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HighlightDisplayLevel getHighlightDisplayLevel() {
|
||||
return HighlightDisplayLevel.find(SpellCheckerSeveritiesProvider.TYPO);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public List<String> getSuggestions(@NotNull String word) {
|
||||
public List<String> getSuggestions(@NotNull String text) {
|
||||
return suggestionProvider.getSuggestions(text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@NotNull
|
||||
protected List<String> getRawSuggestions(@NotNull String word) {
|
||||
if (!spellChecker.isCorrect(word)) {
|
||||
List<String> suggestions = spellChecker.getSuggestions(word, MAX_SUGGESTIONS_THRESHOLD, MAX_METRICS);
|
||||
if (suggestions.size() != 0) {
|
||||
@@ -144,5 +189,4 @@ public class SpellCheckerManager {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.spellchecker.dictionary.Loader;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class StreamLoader implements Loader {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.StreamLoader");
|
||||
|
||||
private InputStream stream;
|
||||
|
||||
public StreamLoader(InputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
|
||||
public void load(@NotNull Consumer<String> consumer) {
|
||||
DataInputStream in = new DataInputStream(stream);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
try {
|
||||
String strLine;
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
consumer.consume(strLine);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
br.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
package com.intellij.spellchecker.dictionary;
|
||||
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public interface Loader {
|
||||
|
||||
void load(@NotNull Processor processor);
|
||||
void load(@NotNull Consumer<String> consumer);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
*/
|
||||
package com.intellij.spellchecker.engine;
|
||||
|
||||
import com.intellij.spellchecker.dictionary.*;
|
||||
import com.intellij.spellchecker.dictionary.Dictionary;
|
||||
import com.intellij.spellchecker.dictionary.Loader;
|
||||
import com.intellij.spellchecker.dictionary.UserDictionary;
|
||||
import com.intellij.spellchecker.trie.Action;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -34,8 +37,8 @@ public class BaseSpellChecker implements SpellCheckerEngine {
|
||||
|
||||
private Metrics metrics = new LevenshteinDistance();
|
||||
|
||||
private Processor processor = new Processor() {
|
||||
public void process(@Nullable String word) {
|
||||
private Consumer<String> consumer = new Consumer<String>() {
|
||||
public void consume(@Nullable String word) {
|
||||
final String transformed = transform.transform(word);
|
||||
if (transformed != null) {
|
||||
engineDictionary.addToDictionary(transformed);
|
||||
@@ -48,7 +51,7 @@ public class BaseSpellChecker implements SpellCheckerEngine {
|
||||
}
|
||||
|
||||
public void loadDictionary(@NotNull Loader loader) {
|
||||
loader.load(processor);
|
||||
loader.load(consumer);
|
||||
}
|
||||
|
||||
public Transformation getTransformation() {
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
package com.intellij.spellchecker.engine;
|
||||
|
||||
public final class SpellCheckerFactory {
|
||||
private SpellCheckerFactory() {
|
||||
}
|
||||
private SpellCheckerFactory() {
|
||||
}
|
||||
|
||||
public static SpellCheckerEngine create() {
|
||||
return new BaseSpellChecker();
|
||||
}
|
||||
public static SpellCheckerEngine create() {
|
||||
return new BaseSpellChecker();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+7
-4
@@ -13,11 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.spellchecker.dictionary;
|
||||
package com.intellij.spellchecker.engine;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface Processor {
|
||||
import java.util.List;
|
||||
|
||||
void process(@Nullable String word);
|
||||
public interface SuggestionProvider {
|
||||
|
||||
@NotNull
|
||||
List<String> getSuggestions(@NotNull String text);
|
||||
}
|
||||
+31
-15
@@ -49,6 +49,9 @@ import java.util.Map;
|
||||
|
||||
|
||||
public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
|
||||
public static final String SPELL_CHECKING_INSPECTION_TOOL_NAME = "SpellCheckingInspection";
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
public String getGroupDisplayName() {
|
||||
@@ -64,7 +67,7 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
@NonNls
|
||||
@NotNull
|
||||
public String getShortName() {
|
||||
return "SpellCheckingInspection";
|
||||
return SPELL_CHECKING_INSPECTION_TOOL_NAME;
|
||||
}
|
||||
|
||||
public boolean isEnabledByDefault() {
|
||||
@@ -79,19 +82,19 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
private static final Map<Language, SpellcheckingStrategy> factories = new HashMap<Language, SpellcheckingStrategy>();
|
||||
|
||||
private static void ensureFactoriesAreLoaded() {
|
||||
synchronized (factories) {
|
||||
if (!factories.isEmpty()) return;
|
||||
final SpellcheckingStrategy[] spellcheckingStrategies = Extensions.getExtensions(SpellcheckingStrategy.EP_NAME);
|
||||
if (spellcheckingStrategies != null) {
|
||||
for (SpellcheckingStrategy spellcheckingStrategy : spellcheckingStrategies) {
|
||||
final Language language = spellcheckingStrategy.getLanguage();
|
||||
if (language != Language.ANY) {
|
||||
factories.put(language, spellcheckingStrategy);
|
||||
}
|
||||
synchronized (factories) {
|
||||
if (!factories.isEmpty()) return;
|
||||
final SpellcheckingStrategy[] spellcheckingStrategies = Extensions.getExtensions(SpellcheckingStrategy.EP_NAME);
|
||||
if (spellcheckingStrategies != null) {
|
||||
for (SpellcheckingStrategy spellcheckingStrategy : spellcheckingStrategies) {
|
||||
final Language language = spellcheckingStrategy.getLanguage();
|
||||
if (language != Language.ANY) {
|
||||
factories.put(language, spellcheckingStrategy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static SpellcheckingStrategy getFactoryByLanguage(@NotNull Language lang) {
|
||||
@@ -106,7 +109,7 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
public void visitElement(final PsiElement element) {
|
||||
|
||||
final ASTNode node = element.getNode();
|
||||
if (node == null){
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
// Extract parser definition from element
|
||||
@@ -115,17 +118,18 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language);
|
||||
|
||||
// Handle selected options
|
||||
if (parserDefinition != null){
|
||||
if (parserDefinition != null) {
|
||||
if (parserDefinition.getStringLiteralElements().contains(elementType)) {
|
||||
if (!processLiterals){
|
||||
if (!processLiterals) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (parserDefinition.getCommentTokens().contains(elementType)) {
|
||||
if (!processComments){
|
||||
if (!processComments) {
|
||||
return;
|
||||
}
|
||||
} else if (!processCode){
|
||||
}
|
||||
else if (!processCode) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -246,6 +250,18 @@ public class SpellCheckingInspection extends LocalInspectionTool {
|
||||
verticalBox.add(new SingleCheckboxOptionsPanel(SpellCheckerBundle.message("process.code"), this, "processCode"));
|
||||
verticalBox.add(new SingleCheckboxOptionsPanel(SpellCheckerBundle.message("process.literals"), this, "processLiterals"));
|
||||
verticalBox.add(new SingleCheckboxOptionsPanel(SpellCheckerBundle.message("process.comments"), this, "processComments"));
|
||||
/*HyperlinkLabel linkToSettings = new HyperlinkLabel(SpellCheckerBundle.message("link.to.settings"));
|
||||
linkToSettings.addHyperlinkListener(new HyperlinkListener() {
|
||||
public void hyperlinkUpdate(final HyperlinkEvent e) {
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
final OptionsEditor optionsEditor = OptionsEditor.KEY.getData(DataManager.getInstance().getDataContext());
|
||||
// ??project?
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
verticalBox.add(linkToSettings);*/
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(verticalBox, BorderLayout.NORTH);
|
||||
return panel;
|
||||
|
||||
@@ -91,6 +91,7 @@ dirs
|
||||
fileset
|
||||
filesets
|
||||
javadoc
|
||||
|
||||
spellchecker
|
||||
spellchecking
|
||||
|
||||
|
||||
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.options;
|
||||
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.spellchecker.SpellCheckerManager;
|
||||
import com.intellij.spellchecker.util.SpellCheckerBundle;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public final class SpellCheckerConfigurable implements Configurable {
|
||||
private SpellCheckerOptions options;
|
||||
private SpellCheckerManager manager;
|
||||
private final Project myProject;
|
||||
|
||||
|
||||
public SpellCheckerConfigurable(Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Nls
|
||||
public String getDisplayName() {
|
||||
return SpellCheckerBundle.message("spelling");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Icon getIcon() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NonNls
|
||||
public String getHelpTopic() {
|
||||
return "reference.settings.ide.settings.spelling";
|
||||
}
|
||||
|
||||
public JComponent createComponent() {
|
||||
manager = SpellCheckerManager.getInstance(myProject);
|
||||
if (options == null) {
|
||||
options = new SpellCheckerOptions(manager);
|
||||
}
|
||||
return options.getRoot();
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
if (options != null) {
|
||||
return wordsListIsModified();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean wordsListIsModified() {
|
||||
assert options != null;
|
||||
List<String> newWords = options.getWords();
|
||||
Set<String> words = manager.getUserDictionary().getEditableWords();
|
||||
if (words == null && newWords == null) {
|
||||
return false;
|
||||
}
|
||||
if (words == null || newWords == null || newWords.size() != words.size()) {
|
||||
return true;
|
||||
}
|
||||
return !(words.containsAll(newWords) && newWords.containsAll(words));
|
||||
}
|
||||
|
||||
|
||||
public void apply() throws ConfigurationException {
|
||||
manager.updateUserWords(options.getWords());
|
||||
}
|
||||
|
||||
|
||||
public void reset() {
|
||||
}
|
||||
|
||||
public void disposeUIResources() {
|
||||
if (options != null) {
|
||||
options.dispose();
|
||||
options = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.spellchecker.options.SpellCheckerOptions">
|
||||
<grid id="27dc6" binding="root" default-binding="true" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="387" height="285"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<hspacer id="f0925">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<grid id="37249" binding="wordPanelHolder" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="dda13" class="com.intellij.spellchecker.options.SpellCheckerOptions$WordsPanel" binding="wordsPanel" custom-create="true" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<buttonGroups>
|
||||
<group name="additionalDic">
|
||||
<member id="76b15"/>
|
||||
<member id="4ba70"/>
|
||||
</group>
|
||||
</buttonGroups>
|
||||
<inspectionSuppressions>
|
||||
<suppress inspection="NoLabelFor" id="253a1"/>
|
||||
<suppress inspection="NoLabelFor" id="32995"/>
|
||||
</inspectionSuppressions>
|
||||
</form>
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.options;
|
||||
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.spellchecker.SpellCheckerManager;
|
||||
import com.intellij.spellchecker.dictionary.Dictionary;
|
||||
import com.intellij.spellchecker.util.SpellCheckerBundle;
|
||||
import com.intellij.spellchecker.util.Strings;
|
||||
import com.intellij.ui.AddDeleteListPanel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class SpellCheckerOptions implements Disposable {
|
||||
|
||||
private final SpellCheckerManager manager;
|
||||
private JPanel root;
|
||||
private JPanel wordPanelHolder;
|
||||
private WordsPanel wordsPanel;
|
||||
|
||||
|
||||
|
||||
public SpellCheckerOptions(SpellCheckerManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public void createUIComponents() {
|
||||
wordsPanel = new WordsPanel(manager);
|
||||
|
||||
}
|
||||
|
||||
public JPanel getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getWords(){
|
||||
Object[] pairs = wordsPanel.getListItems();
|
||||
if (pairs==null){
|
||||
return null;
|
||||
}
|
||||
List<String> words = new ArrayList<String>();
|
||||
for (Object pair : pairs) {
|
||||
words.add(pair.toString());
|
||||
}
|
||||
return words;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
||||
wordsPanel.dispose();
|
||||
}
|
||||
|
||||
|
||||
public static final class WordDescriber {
|
||||
private Dictionary dictionary;
|
||||
|
||||
public WordDescriber(Dictionary dictionary) {
|
||||
this.dictionary = dictionary;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Pair> process() {
|
||||
if (this.dictionary == null) {
|
||||
return new ArrayList<Pair>();
|
||||
}
|
||||
Set<String> words = this.dictionary.getEditableWords();
|
||||
if (words == null) {
|
||||
return new ArrayList<Pair>();
|
||||
}
|
||||
List<Pair> result = new ArrayList<Pair>();
|
||||
for (String word : words) {
|
||||
result.add(new Pair(word, ""));
|
||||
}
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Pair implements Comparable {
|
||||
private String word;
|
||||
private String description;
|
||||
|
||||
public Pair(@NotNull String word, String description) {
|
||||
this.word = word;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getWord() {
|
||||
return word;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
if (!(o instanceof Pair)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return word.compareTo(((Pair)o).getWord());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return word + (description!=null && description.trim().length()>0?"("+description+")":"");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class WordsPanel extends AddDeleteListPanel implements Disposable {
|
||||
private SpellCheckerManager manager;
|
||||
|
||||
private WordsPanel(SpellCheckerManager manager) {
|
||||
super(null, new WordDescriber(manager.getUserDictionary()).process());
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
|
||||
protected Object findItemToAdd() {
|
||||
String word = Messages.showInputDialog(com.intellij.spellchecker.util.SpellCheckerBundle.message("enter.simple.word"),
|
||||
SpellCheckerBundle.message("add.new.word"), null);
|
||||
if (word == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
word = word.trim();
|
||||
}
|
||||
|
||||
if (Strings.isMixedCase(word)) {
|
||||
Messages.showWarningDialog(SpellCheckerBundle.message("entered.word.0.is.mixed.cased.you.must.enter.simple.word", word),
|
||||
SpellCheckerBundle.message("add.new.word"));
|
||||
return null;
|
||||
}
|
||||
if (!manager.hasProblem(word)) {
|
||||
Messages.showWarningDialog(SpellCheckerBundle.message("entered.word.0.is.correct.you.no.need.to.add.this.in.list", word),
|
||||
SpellCheckerBundle.message("add.new.word"));
|
||||
return null;
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
myListModel.removeAllElements();
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-44
@@ -18,12 +18,14 @@ package com.intellij.spellchecker.quickfixes;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.codeStyle.NameUtil;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.refactoring.rename.NameSuggestionProvider;
|
||||
import com.intellij.spellchecker.SpellCheckerManager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
public class DictionarySuggestionProvider implements NameSuggestionProvider {
|
||||
@@ -49,49 +51,8 @@ public class DictionarySuggestionProvider implements NameSuggestionProvider {
|
||||
|
||||
SpellCheckerManager manager = SpellCheckerManager.getInstance(element.getProject());
|
||||
|
||||
String[] words = NameUtil.nameToWords(text);
|
||||
|
||||
int index = 0;
|
||||
List[] res = new List[words.length];
|
||||
int i = 0;
|
||||
for (String word : words) {
|
||||
int start = text.indexOf(word, index);
|
||||
int end = start + word.length();
|
||||
if (!manager.hasProblem(word)) {
|
||||
List<String> variants = new ArrayList<String>();
|
||||
variants.add(word);
|
||||
res[i++] = variants;
|
||||
}
|
||||
else {
|
||||
List<String> variants = manager.getSuggestions(word);
|
||||
res[i++] = variants;
|
||||
}
|
||||
index = end;
|
||||
}
|
||||
|
||||
String[] all = null;
|
||||
int counter[] = new int[i];
|
||||
int size = 1;
|
||||
for (int j = 0; j < i; j++) {
|
||||
size *= res[j].size();
|
||||
}
|
||||
all = new String[size];
|
||||
|
||||
for (int k = 0; k < size; k++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (all[k] == null) {
|
||||
all[k] = "";
|
||||
}
|
||||
all[k] += res[j].get(counter[j]);
|
||||
counter[j]++;
|
||||
if (counter[j] >= res[j].size()) {
|
||||
counter[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> set = new TreeSet<String>();
|
||||
set.addAll(Arrays.asList(all));
|
||||
set.addAll(manager.getSuggestions(text));
|
||||
result.addAll(set);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,6 @@ public abstract class ShowSuggestions implements LocalQuickFix, Iconable {
|
||||
private boolean processed;
|
||||
|
||||
|
||||
|
||||
|
||||
public ShowSuggestions(@NotNull TextRange textRange, @NotNull String word, @NotNull Project project) {
|
||||
this.textRange = textRange;
|
||||
this.word = word;
|
||||
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.settings;
|
||||
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@State(
|
||||
name = "SpellCheckerSettings",
|
||||
storages = {@Storage(
|
||||
id = "other",
|
||||
file = "$PROJECT_FILE$"),
|
||||
@Storage(
|
||||
id = "dir",
|
||||
file = "$PROJECT_CONFIG_DIR$/spellchecker-settings.xml",
|
||||
scheme = StorageScheme.DIRECTORY_BASED)})
|
||||
public class SpellCheckerSettings implements PersistentStateComponent<Element> {
|
||||
// For xml serialization
|
||||
private static final String SPELLCHECKER_MANAGER_SETTINGS_TAG = "SpellCheckerSettings";
|
||||
|
||||
private static final String FOLDERS_ATTR_NAME = "Folders";
|
||||
private static final String FOLDER_ATTR_NAME = "Folder";
|
||||
private static final String DICTIONARIES_ATTR_NAME = "Dictionaries";
|
||||
private static final String DICTIONARY_ATTR_NAME = "Dictionary";
|
||||
|
||||
private static final String BUNDLED_DICTIONARIES_ATTR_NAME = "BundledDictionaries";
|
||||
private static final String BUNDLED_DICTIONARY_ATTR_NAME = "BundledDictionary";
|
||||
|
||||
// Paths
|
||||
private List<String> myDictionaryFoldersPaths = new ArrayList<String>();
|
||||
private Set<String> myDisabledDictionariesPaths = new HashSet<String>();
|
||||
|
||||
private Set<String> myBundledDisabledDictionariesPaths = new HashSet<String>();
|
||||
|
||||
public static SpellCheckerSettings getInstance(Project project){
|
||||
return ServiceManager.getService(project,SpellCheckerSettings.class);
|
||||
}
|
||||
|
||||
|
||||
public List<String> getDictionaryFoldersPaths() {
|
||||
return myDictionaryFoldersPaths;
|
||||
}
|
||||
|
||||
public void setDictionaryFoldersPaths(List<String> dictionaryFoldersPaths) {
|
||||
myDictionaryFoldersPaths = dictionaryFoldersPaths;
|
||||
}
|
||||
|
||||
public Set<String> getDisabledDictionariesPaths() {
|
||||
return myDisabledDictionariesPaths;
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getEnabledDictionariesPaths() {
|
||||
final HashSet<String> enabledDictionaries = new HashSet<String>();
|
||||
for (String folder : myDictionaryFoldersPaths) {
|
||||
/*RFileUtil.processFilesRecursively(folder, new Consumer<String>() {
|
||||
public void consume(final String s) {
|
||||
if (!myDisabledDictionariesPaths.contains(s)){
|
||||
enabledDictionaries.add(s);
|
||||
}
|
||||
}
|
||||
});*/
|
||||
}
|
||||
return enabledDictionaries;
|
||||
}
|
||||
|
||||
public Set<String> getBundledEnabledDictionariesPaths() {
|
||||
final HashSet<String> bundledEnabledDictionaries = new HashSet<String>();
|
||||
final List<String> builtInFolders = getBundledDictionariesFoldersPaths();
|
||||
for (String folder : builtInFolders) {
|
||||
/*RFileUtil.processFilesRecursively(folder, new Consumer<String>() {
|
||||
public void consume(final String s) {
|
||||
if (!myBundledDisabledDictionariesPaths.contains(s)){
|
||||
bundledEnabledDictionaries.add(s);
|
||||
}
|
||||
}
|
||||
});*/
|
||||
}
|
||||
return bundledEnabledDictionaries;
|
||||
}
|
||||
|
||||
public void setDisabledDictionariesPaths(Set<String> disabledDictionariesPaths) {
|
||||
myDisabledDictionariesPaths = disabledDictionariesPaths;
|
||||
}
|
||||
|
||||
public List<String> getBundledDictionariesFoldersPaths() {
|
||||
/*return Collections.unmodifiableList(RubySupportLoader.getBuiltinScriptFolders());*/
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Set<String> getBundledDisabledDictionariesPaths() {
|
||||
return myBundledDisabledDictionariesPaths;
|
||||
}
|
||||
|
||||
public void setBundledDisabledDictionariesPaths(Set<String> bundledDisabledDictionariesPaths) {
|
||||
myBundledDisabledDictionariesPaths = bundledDisabledDictionariesPaths;
|
||||
}
|
||||
|
||||
public Element getState() {
|
||||
final Element element = new Element(SPELLCHECKER_MANAGER_SETTINGS_TAG);
|
||||
// bundled
|
||||
element.setAttribute(BUNDLED_DICTIONARIES_ATTR_NAME, String.valueOf(myBundledDisabledDictionariesPaths.size()));
|
||||
Iterator<String> iterator = myBundledDisabledDictionariesPaths.iterator();
|
||||
int i=0;
|
||||
while (iterator.hasNext()){
|
||||
element.setAttribute(BUNDLED_DICTIONARY_ATTR_NAME + i, iterator.next());
|
||||
i++;
|
||||
}
|
||||
// user
|
||||
element.setAttribute(FOLDERS_ATTR_NAME, String.valueOf(myDictionaryFoldersPaths.size()));
|
||||
for (int j=0;j< myDictionaryFoldersPaths.size();j++){
|
||||
element.setAttribute(FOLDER_ATTR_NAME + j, myDictionaryFoldersPaths.get(j));
|
||||
}
|
||||
element.setAttribute(DICTIONARIES_ATTR_NAME, String.valueOf(myDisabledDictionariesPaths.size()));
|
||||
iterator = myDisabledDictionariesPaths.iterator();
|
||||
i=0;
|
||||
while (iterator.hasNext()){
|
||||
element.setAttribute(DICTIONARY_ATTR_NAME + i, iterator.next());
|
||||
i++;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
public void loadState(@NotNull final Element element) {
|
||||
myBundledDisabledDictionariesPaths.clear();
|
||||
myDictionaryFoldersPaths.clear();
|
||||
myDisabledDictionariesPaths.clear();
|
||||
try {
|
||||
// bundled
|
||||
final int bundledDictionariesSize = Integer.valueOf(element.getAttributeValue(BUNDLED_DICTIONARIES_ATTR_NAME));
|
||||
for (int i=0;i<bundledDictionariesSize;i++){
|
||||
myBundledDisabledDictionariesPaths.add(element.getAttributeValue(BUNDLED_DICTIONARY_ATTR_NAME + i));
|
||||
}
|
||||
// user
|
||||
final int foldersSize = Integer.valueOf(element.getAttributeValue(FOLDERS_ATTR_NAME));
|
||||
for (int i=0;i<foldersSize;i++){
|
||||
myDictionaryFoldersPaths.add(element.getAttributeValue(FOLDER_ATTR_NAME + i));
|
||||
}
|
||||
final int scriptsSize = Integer.valueOf(element.getAttributeValue(DICTIONARIES_ATTR_NAME));
|
||||
for (int i=0;i<scriptsSize;i++){
|
||||
myDisabledDictionariesPaths.add(element.getAttributeValue(DICTIONARY_ATTR_NAME + i));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.settings;
|
||||
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.spellchecker.util.SpellCheckerBundle;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class SpellCheckerSettingsManager implements Configurable {
|
||||
private SpellCheckerSettingsPane settingsPane;
|
||||
private SpellCheckerSettings settings;
|
||||
private Project project;
|
||||
|
||||
public static SpellCheckerSettingsManager getInstance(Project project) {
|
||||
return ShowSettingsUtil.getInstance().findProjectConfigurable(project, SpellCheckerSettingsManager.class);
|
||||
}
|
||||
|
||||
public SpellCheckerSettingsManager(Project project) {
|
||||
this.project = project;
|
||||
settings = SpellCheckerSettings.getInstance(project);
|
||||
}
|
||||
|
||||
@Nls
|
||||
public String getDisplayName() {
|
||||
return SpellCheckerBundle.message("spelling");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Icon getIcon() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NonNls
|
||||
public String getHelpTopic() {
|
||||
return "reference.settings.ide.settings.spelling";
|
||||
}
|
||||
|
||||
|
||||
public JComponent createComponent() {
|
||||
if (settingsPane == null) {
|
||||
settingsPane = new SpellCheckerSettingsPane(settings,project);
|
||||
}
|
||||
return settingsPane.getPane();
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return settingsPane == null || settingsPane.isModified();
|
||||
}
|
||||
|
||||
public void apply() throws ConfigurationException {
|
||||
if (settingsPane != null) {
|
||||
settingsPane.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
if (settingsPane != null) {
|
||||
settingsPane.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void disposeUIResources() {
|
||||
settingsPane = null;
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.spellchecker.settings.SpellCheckerSettingsPane">
|
||||
<grid id="27dc6" binding="root" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="3de32" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="439de" binding="linkContainer" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="24" height="38"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="6126a" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<tabbedpane id="b70bc" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="200" height="200"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="ba93e" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<tabbedpane title="Accepted Words"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="425d4" binding="panelForAcceptedWords" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="b6b2d" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<tabbedpane title="Dictionaries"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="b9ce9" binding="panelForDictionaryChooser" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="etched" title="Dictionaries"/>
|
||||
<children/>
|
||||
</grid>
|
||||
<grid id="3d135" binding="panelForFolderChooser" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="etched" title="User Dictionaries Path"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</tabbedpane>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.settings;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.newEditor.OptionsEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.profile.codeInspection.ui.ProjectInspectionToolsConfigurable;
|
||||
import com.intellij.spellchecker.SpellCheckerManager;
|
||||
import com.intellij.spellchecker.dictionary.Dictionary;
|
||||
import com.intellij.spellchecker.util.SPFileUtil;
|
||||
import com.intellij.spellchecker.util.SpellCheckerBundle;
|
||||
import com.intellij.spellchecker.util.Strings;
|
||||
import com.intellij.ui.AddDeleteListPanel;
|
||||
import com.intellij.ui.HyperlinkLabel;
|
||||
import com.intellij.ui.OptionalChooserComponent;
|
||||
import com.intellij.ui.PathsChooserComponent;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class SpellCheckerSettingsPane implements Disposable {
|
||||
private JPanel root;
|
||||
private JPanel linkContainer;
|
||||
private JPanel panelForDictionaryChooser;
|
||||
private JPanel panelForAcceptedWords;
|
||||
private JPanel panelForFolderChooser;
|
||||
private OptionalChooserComponent optionalChooserComponent;
|
||||
private PathsChooserComponent pathsChooserComponent;
|
||||
private final List<Pair<String, Boolean>> allDictionaries = new ArrayList<Pair<String, Boolean>>();
|
||||
private final List<String> dictionariesFolders = new ArrayList<String>();
|
||||
private final WordsPanel wordsPanel;
|
||||
private final SpellCheckerManager manager;
|
||||
private final SpellCheckerSettings settings;
|
||||
|
||||
public SpellCheckerSettingsPane(SpellCheckerSettings settings, final Project project) {
|
||||
this.settings = settings;
|
||||
manager = SpellCheckerManager.getInstance(project);
|
||||
HyperlinkLabel link = new HyperlinkLabel(SpellCheckerBundle.message("link.to.inspection.settings"));
|
||||
link.addHyperlinkListener(new HyperlinkListener() {
|
||||
public void hyperlinkUpdate(final HyperlinkEvent e) {
|
||||
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
final OptionsEditor optionsEditor = OptionsEditor.KEY.getData(DataManager.getInstance().getDataContext());
|
||||
final ProjectInspectionToolsConfigurable toolsConfigurable = ProjectInspectionToolsConfigurable.getInstance(project);
|
||||
if (optionsEditor != null && toolsConfigurable != null) {
|
||||
optionsEditor.select(toolsConfigurable).doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
toolsConfigurable.selectInspectionTool("SpellCheckingInspection");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
linkContainer.setLayout(new BorderLayout());
|
||||
linkContainer.add(link);
|
||||
|
||||
// Fill in all the dictionaries folders (not implemented yet) and enabled dictionaries
|
||||
fillAllDictionaries();
|
||||
|
||||
|
||||
pathsChooserComponent = new PathsChooserComponent(dictionariesFolders, new PathsChooserComponent.PathProcessor() {
|
||||
public boolean addPath(List<String> paths, String path) {
|
||||
if (paths.contains(path)) {
|
||||
final String title = SpellCheckerBundle.message("add.directory.title");
|
||||
final String msg = SpellCheckerBundle.message("directory.is.already.included");
|
||||
Messages.showErrorDialog(root, msg, title);
|
||||
return false;
|
||||
}
|
||||
paths.add(path);
|
||||
|
||||
final ArrayList<Pair<String, Boolean>> currentDictionaries = optionalChooserComponent.getValue();
|
||||
SPFileUtil.processFilesRecursively(path, new Consumer<String>() {
|
||||
public void consume(final String s) {
|
||||
currentDictionaries.add(Pair.create(s, true));
|
||||
}
|
||||
});
|
||||
optionalChooserComponent.update();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean removePath(List<String> paths, String path) {
|
||||
if (paths.remove(path)) {
|
||||
final ArrayList<Pair<String, Boolean>> result = new ArrayList<Pair<String, Boolean>>();
|
||||
final ArrayList<Pair<String, Boolean>> currentDictionaries = optionalChooserComponent.getValue();
|
||||
for (Pair<String, Boolean> pair : currentDictionaries) {
|
||||
if (!pair.first.startsWith(path)) {
|
||||
result.add(pair);
|
||||
}
|
||||
}
|
||||
currentDictionaries.clear();
|
||||
currentDictionaries.addAll(result);
|
||||
optionalChooserComponent.update();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
panelForFolderChooser.setLayout(new BorderLayout());
|
||||
panelForFolderChooser.add(pathsChooserComponent.getContentPane(), BorderLayout.CENTER);
|
||||
|
||||
|
||||
optionalChooserComponent = new OptionalChooserComponent(allDictionaries) {
|
||||
@Override
|
||||
public JCheckBox createCheckBox(String path, boolean checked) {
|
||||
if (isUserDictionary(path)) {
|
||||
path = FileUtil.toSystemIndependentName(path);
|
||||
final int i = path.lastIndexOf('/');
|
||||
if (i != -1) {
|
||||
final String name = path.substring(i + 1);
|
||||
return new JCheckBox("[user] " + name, checked);
|
||||
}
|
||||
}
|
||||
return new JCheckBox("[bundled] " + FileUtil.toSystemDependentName(path), checked);
|
||||
}
|
||||
};
|
||||
|
||||
panelForDictionaryChooser.setLayout(new BorderLayout());
|
||||
panelForDictionaryChooser.add(optionalChooserComponent.getContentPane(), BorderLayout.CENTER);
|
||||
|
||||
|
||||
wordsPanel = new WordsPanel(manager);
|
||||
panelForAcceptedWords.setLayout(new BorderLayout());
|
||||
panelForAcceptedWords.add(wordsPanel, BorderLayout.CENTER);
|
||||
|
||||
}
|
||||
|
||||
public JComponent getPane() {
|
||||
return root;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return wordsPanel.isModified() || optionalChooserComponent.isModified();
|
||||
}
|
||||
|
||||
public void apply() throws ConfigurationException {
|
||||
optionalChooserComponent.apply();
|
||||
pathsChooserComponent.apply();
|
||||
settings.setDictionaryFoldersPaths(pathsChooserComponent.getValues());
|
||||
|
||||
final HashSet<String> disabledDictionaries = new HashSet<String>();
|
||||
final HashSet<String> bundledDisabledDictionaries = new HashSet<String>();
|
||||
for (Pair<String, Boolean> pair : allDictionaries) {
|
||||
if (!pair.second) {
|
||||
final String scriptPath = pair.first;
|
||||
if (isUserDictionary(scriptPath)) {
|
||||
disabledDictionaries.add(scriptPath);
|
||||
}
|
||||
else {
|
||||
bundledDisabledDictionaries.add(scriptPath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
settings.setDisabledDictionariesPaths(disabledDictionaries);
|
||||
settings.setBundledDisabledDictionariesPaths(bundledDisabledDictionaries);
|
||||
|
||||
manager.update(wordsPanel.getWords(), settings);
|
||||
}
|
||||
|
||||
private boolean isUserDictionary(final String dictionary) {
|
||||
boolean isUserDictionary = false;
|
||||
for (String dictionaryFolder : pathsChooserComponent.getValues()) {
|
||||
if (dictionary.startsWith(dictionaryFolder)) {
|
||||
isUserDictionary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isUserDictionary;
|
||||
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
pathsChooserComponent.reset();
|
||||
fillAllDictionaries();
|
||||
optionalChooserComponent.reset();
|
||||
}
|
||||
|
||||
|
||||
private void fillAllDictionaries() {
|
||||
dictionariesFolders.clear();
|
||||
dictionariesFolders.addAll(settings.getDictionaryFoldersPaths());
|
||||
allDictionaries.clear();
|
||||
for (String dictionary : manager.getBundledDictionaries()) {
|
||||
allDictionaries.add(new Pair<String, Boolean>(dictionary, !settings.getBundledDisabledDictionariesPaths().contains(dictionary)));
|
||||
}
|
||||
|
||||
// user
|
||||
//todo [shkate]: refactoring - SpellCheckerManager contains the same code withing reloadConfiguration()
|
||||
final Set<String> disabledDictionaries = settings.getDisabledDictionariesPaths();
|
||||
for (String folder : dictionariesFolders) {
|
||||
SPFileUtil.processFilesRecursively(folder, new Consumer<String>() {
|
||||
public void consume(final String s) {
|
||||
allDictionaries.add(Pair.create(s, !disabledDictionaries.contains(s)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
if (wordsPanel != null) {
|
||||
wordsPanel.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static final class WordDescriber {
|
||||
private Dictionary dictionary;
|
||||
|
||||
public WordDescriber(Dictionary dictionary) {
|
||||
this.dictionary = dictionary;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> process() {
|
||||
if (this.dictionary == null) {
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
Set<String> words = this.dictionary.getEditableWords();
|
||||
if (words == null) {
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (String word : words) {
|
||||
result.add(word);
|
||||
}
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class WordsPanel extends AddDeleteListPanel implements Disposable {
|
||||
private SpellCheckerManager manager;
|
||||
|
||||
private WordsPanel(SpellCheckerManager manager) {
|
||||
super(null, new WordDescriber(manager.getUserDictionary()).process());
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
|
||||
protected Object findItemToAdd() {
|
||||
String word = Messages.showInputDialog(com.intellij.spellchecker.util.SpellCheckerBundle.message("enter.simple.word"),
|
||||
SpellCheckerBundle.message("add.new.word"), null);
|
||||
if (word == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
word = word.trim();
|
||||
}
|
||||
|
||||
if (Strings.isMixedCase(word)) {
|
||||
Messages.showWarningDialog(SpellCheckerBundle.message("entered.word.0.is.mixed.cased.you.must.enter.simple.word", word),
|
||||
SpellCheckerBundle.message("add.new.word"));
|
||||
return null;
|
||||
}
|
||||
if (!manager.hasProblem(word)) {
|
||||
Messages.showWarningDialog(SpellCheckerBundle.message("entered.word.0.is.correct.you.no.need.to.add.this.in.list", word),
|
||||
SpellCheckerBundle.message("add.new.word"));
|
||||
return null;
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
myListModel.removeAllElements();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getWords() {
|
||||
Object[] pairs = getListItems();
|
||||
if (pairs == null) {
|
||||
return null;
|
||||
}
|
||||
List<String> words = new ArrayList<String>();
|
||||
for (Object pair : pairs) {
|
||||
words.add(pair.toString());
|
||||
}
|
||||
return words;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
List<String> newWords = getWords();
|
||||
Set<String> words = manager.getUserDictionary().getEditableWords();
|
||||
if (words == null && newWords == null) {
|
||||
return false;
|
||||
}
|
||||
if (words == null || newWords == null || newWords.size() != words.size()) {
|
||||
return true;
|
||||
}
|
||||
return !(words.containsAll(newWords) && newWords.containsAll(words));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.spellchecker.dictionary.Dictionary;
|
||||
import com.intellij.spellchecker.dictionary.Loader;
|
||||
import com.intellij.spellchecker.dictionary.Processor;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -35,7 +35,7 @@ public class StateLoader implements Loader {
|
||||
}
|
||||
|
||||
|
||||
public void load(@NotNull Processor processor) {
|
||||
public void load(@NotNull Consumer<String> consumer) {
|
||||
AggregatedDictionaryState state = ServiceManager.getService(project, AggregatedDictionaryState.class);
|
||||
state.setProject(project);
|
||||
state.loadState();
|
||||
@@ -43,7 +43,7 @@ public class StateLoader implements Loader {
|
||||
final Set<String> storedWords = dictionary.getWords();
|
||||
if (storedWords!=null){
|
||||
for (String word : storedWords) {
|
||||
processor.process(word);
|
||||
consumer.consume(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.util;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"})
|
||||
public class SPFileUtil {
|
||||
|
||||
public static void processFilesRecursively(final String rootPath, final Consumer<String> consumer){
|
||||
final File rootFile = new File(rootPath);
|
||||
if (rootFile.exists() && rootFile.isDirectory()){
|
||||
FileUtil.processFilesRecursively(rootFile, new Processor<File>() {
|
||||
public boolean process(final File file) {
|
||||
if (!file.isDirectory()){
|
||||
final String path = file.getPath();
|
||||
if (path.endsWith(".dic")){
|
||||
consumer.consume(path);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,3 +25,8 @@ no.suggestions=<no suggestion>
|
||||
process.code=Process code
|
||||
process.literals=Process literals
|
||||
process.comments=Process comments
|
||||
link.to.settings=Manage Dictionaries
|
||||
link.to.inspection.settings=Manage spelling inspection settings
|
||||
exact.rename.to=Typo: Rename to ''{0}''
|
||||
add.directory.title=User Dictionary Path
|
||||
directory.is.already.included=Directory is already included
|
||||
|
||||
+18
-6
@@ -23,19 +23,31 @@ import java.util.List;
|
||||
|
||||
public class SuggestionTest extends JavaCodeInsightFixtureTestCase {
|
||||
|
||||
private SpellCheckerManager spManager;
|
||||
private SpellCheckerManager getManager(){
|
||||
if (spManager==null){
|
||||
spManager = SpellCheckerManager.getInstance(getProject());
|
||||
}
|
||||
assert spManager!=null;
|
||||
return spManager;
|
||||
}
|
||||
|
||||
public void testSuggestions(){
|
||||
SpellCheckerManager manager = SpellCheckerManager.getInstance(getProject());
|
||||
assert manager!=null;
|
||||
List<String> result = manager.getSuggestions("upgade");
|
||||
assertEquals(result.get(0),"upgrade");
|
||||
List<String> result = getManager().getSuggestions("upgade");
|
||||
assertEquals("upgrade",result.get(0));
|
||||
}
|
||||
|
||||
|
||||
public void testFirstLetterUppercaseSuggestions(){
|
||||
List<String> result = getManager().getSuggestions("Upgade");
|
||||
assertEquals("Upgrade",result.get(0));
|
||||
}
|
||||
|
||||
public void testCamelCaseSuggestions(){
|
||||
SpellCheckerManager manager = SpellCheckerManager.getInstance(getProject());
|
||||
assert manager!=null;
|
||||
List<String> result = manager.getSuggestions("Upgade");
|
||||
assertEquals(result.get(0),"Upgrade");
|
||||
List<String> result = manager.getSuggestions("TestUpgade");
|
||||
assertEquals("TestUpgrade",result.get(0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user