diff options
Diffstat (limited to 'platform/lang-api/src/com/intellij')
29 files changed, 696 insertions, 143 deletions
diff --git a/platform/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java b/platform/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java index b45abc181736..4991071477fb 100644 --- a/platform/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java +++ b/platform/lang-api/src/com/intellij/diagnostic/logging/AdditionalTabComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.diagnostic.logging; import com.intellij.openapi.ui.ComponentContainer; @@ -36,6 +35,7 @@ public abstract class AdditionalTabComponent extends JPanel implements Component protected AdditionalTabComponent() { } + @NotNull public abstract String getTabTitle(); @Nullable diff --git a/platform/lang-api/src/com/intellij/execution/DefaultExecutionResult.java b/platform/lang-api/src/com/intellij/execution/DefaultExecutionResult.java index 8a951da7d74f..75f117122e96 100644 --- a/platform/lang-api/src/com/intellij/execution/DefaultExecutionResult.java +++ b/platform/lang-api/src/com/intellij/execution/DefaultExecutionResult.java @@ -34,7 +34,8 @@ public class DefaultExecutionResult implements ExecutionResult { private final ExecutionConsole myConsole; private final ProcessHandler myProcessHandler; private AnAction[] myActions; - private AnAction[] myRestartActions; + @NotNull + private AnAction[] myRestartActions = AnAction.EMPTY_ARRAY; private final List<AnAction> myStopActions = new ArrayList<AnAction>(); public DefaultExecutionResult() { @@ -67,12 +68,14 @@ public class DefaultExecutionResult implements ExecutionResult { myActions = actions; } + @NotNull public AnAction[] getRestartActions() { return myRestartActions; } - public void setRestartActions(AnAction... restartActions) { - myRestartActions = restartActions; + // TODO: Find all usages, make sure there is no null and make this method NotNull + public void setRestartActions(@Nullable AnAction... restartActions) { + myRestartActions = (restartActions != null ? restartActions : AnAction.EMPTY_ARRAY); } public void addStopAction(AnAction action) { @@ -104,7 +107,7 @@ public class DefaultExecutionResult implements ExecutionResult { @Override public void actionPerformed(final AnActionEvent e) { - if(myProcessHandler.detachIsDefault()) { + if (myProcessHandler.detachIsDefault()) { myProcessHandler.detachProcess(); } else { diff --git a/platform/lang-api/src/com/intellij/execution/ExecutionResult.java b/platform/lang-api/src/com/intellij/execution/ExecutionResult.java index 116ce555e94d..91f888aa8dc6 100644 --- a/platform/lang-api/src/com/intellij/execution/ExecutionResult.java +++ b/platform/lang-api/src/com/intellij/execution/ExecutionResult.java @@ -40,6 +40,7 @@ public interface ExecutionResult { */ AnAction[] getActions(); + /** * Returns the ProcessHandler attached to the running process. * diff --git a/platform/lang-api/src/com/intellij/execution/configurations/AdditionalTabComponentManager.java b/platform/lang-api/src/com/intellij/execution/configurations/AdditionalTabComponentManager.java index 26f1273b2698..701f1b294003 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/AdditionalTabComponentManager.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/AdditionalTabComponentManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - /* * Created by IntelliJ IDEA. * User: Anna.Kozlova @@ -23,8 +22,10 @@ package com.intellij.execution.configurations; import com.intellij.diagnostic.logging.AdditionalTabComponent; +import org.jetbrains.annotations.NotNull; public interface AdditionalTabComponentManager { - void addAdditionalTabComponent(AdditionalTabComponent component, final String id); - void removeAdditionalTabComponent(AdditionalTabComponent component); + void addAdditionalTabComponent(@NotNull AdditionalTabComponent component, @NotNull String id); + + void removeAdditionalTabComponent(@NotNull AdditionalTabComponent component); }
\ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java b/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java index 6f23831c9e3a..0a4132d83a52 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java @@ -20,6 +20,8 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.SmartList; +import com.intellij.util.containers.SmartHashSet; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -27,8 +29,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashSet; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.regex.Pattern; @@ -80,46 +81,50 @@ public class LogFileOptions implements JDOMExternalizable { return myPathPattern; } + @NotNull public Set<String> getPaths(){ - Set<String> result = new HashSet<String>(); - final File logFile = new File(myPathPattern); + File logFile = new File(myPathPattern); if (logFile.exists()){ - result.add(myPathPattern); + return Collections.singleton(myPathPattern); + } + + int dirIndex = myPathPattern.lastIndexOf(File.separator); + if (dirIndex == -1) { + return Collections.emptySet(); + } + + List<File> files = new SmartList<File>(); + collectMatchedFiles(new File(myPathPattern.substring(0, dirIndex)), Pattern.compile(FileUtil.convertAntToRegexp(myPathPattern.substring(dirIndex + File.separator.length()))), files); + if (files.isEmpty()) { + return Collections.emptySet(); + } + + if (myShowAll) { + SmartHashSet<String> result = new SmartHashSet<String>(); + result.ensureCapacity(files.size()); + for (File file : files) { + result.add(file.getPath()); + } return result; } - final int dirIndex = myPathPattern.lastIndexOf(File.separator); - if (dirIndex != -1) { - final ArrayList<File> files = new ArrayList<File>(); - final String basePath = myPathPattern.substring(0, dirIndex); - final String pattern = myPathPattern.substring(dirIndex + File.separator.length()); - collectMatchedFiles(new File(basePath), Pattern.compile(FileUtil.convertAntToRegexp(pattern)), files); - if (!files.isEmpty()) { - if (myShowAll) { - for (File file : files) { - result.add(file.getPath()); + else { + File lastFile = null; + for (File file : files) { + if (lastFile != null) { + if (file.lastModified() > lastFile.lastModified()) { + lastFile = file; } } else { - File lastFile = null; - for (File file : files) { - if (lastFile != null) { - if (file.lastModified() > lastFile.lastModified()) { - lastFile = file; - } - } - else { - lastFile = file; - } - } - assert lastFile != null; - result.add(lastFile.getPath()); + lastFile = file; } } + assert lastFile != null; + return Collections.singleton(lastFile.getPath()); } - return result; } - public static void collectMatchedFiles(final File root, final Pattern pattern, final List<File> files) { + public static void collectMatchedFiles(@NotNull File root, @NotNull Pattern pattern, @NotNull List<File> files) { final File[] dirs = root.listFiles(); if (dirs == null) return; for (File dir : dirs) { diff --git a/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java b/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java index 9a1dfad2955a..45519c91baeb 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/ModuleRunProfile.java @@ -19,5 +19,5 @@ package com.intellij.execution.configurations; /** * @author spleaner */ -public interface ModuleRunProfile extends RunProfileWithCompileBeforeLaunchOption { +public interface ModuleRunProfile extends RunProfileWithCompileBeforeLaunchOption, SearchScopeProvidingRunProfile { } diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java index 0e852c6c577a..d0a180114587 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java @@ -154,8 +154,9 @@ public abstract class RunConfigurationBase extends UserDataHolderBase return myPredefinedLogFiles; } + @NotNull public ArrayList<LogFileOptions> getAllLogFiles() { - final ArrayList<LogFileOptions> list = new ArrayList<LogFileOptions>(myLogFiles); + ArrayList<LogFileOptions> list = new ArrayList<LogFileOptions>(myLogFiles); for (PredefinedLogFile predefinedLogFile : myPredefinedLogFiles) { final LogFileOptions options = getOptionsForPredefinedLogFile(predefinedLogFile); if (options != null) { diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationsSettings.java b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationsSettings.java index 259fd4e7484c..732976cf73a7 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationsSettings.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationsSettings.java @@ -17,12 +17,11 @@ package com.intellij.execution.configurations; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.options.UnnamedConfigurable; -import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; public interface RunConfigurationsSettings { ExtensionPointName<RunConfigurationsSettings> EXTENSION_POINT = ExtensionPointName.create("com.intellij.runConfigurationsSettings"); @NotNull - UnnamedConfigurable createConfigurable(@NotNull Project project); + UnnamedConfigurable createConfigurable(); }
\ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java index ea6b158e0bc2..e3f0c22a2132 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvider.java @@ -28,8 +28,8 @@ public class SearchScopeProvider { @NotNull public static GlobalSearchScope createSearchScope(@NotNull Project project, @Nullable RunProfile runProfile) { Module[] modules = null; - if (runProfile instanceof ModuleRunProfile) { - modules = ((ModuleRunProfile)runProfile).getModules(); + if (runProfile instanceof SearchScopeProvidingRunProfile) { + modules = ((SearchScopeProvidingRunProfile)runProfile).getModules(); } if (modules == null || modules.length == 0) { return GlobalSearchScope.allScope(project); diff --git a/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvidingRunProfile.java b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvidingRunProfile.java new file mode 100644 index 000000000000..afdd273384e8 --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/configurations/SearchScopeProvidingRunProfile.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2014 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.execution.configurations; + +import com.intellij.openapi.module.Module; +import org.jetbrains.annotations.NotNull; + +/** + * Base interface for run configurations that can specify which part of the project should be used to search sources. This information + * will be used to provide more accurate navigation to sources from stack traces, debugger, etc + * + * @author nik + */ +public interface SearchScopeProvidingRunProfile extends RunProfile { + /** + * @return modules where to search sources for this configuration + */ + @NotNull + Module[] getModules(); +}
\ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java b/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java index 7b3c45d5c7de..59fe6c2f1be2 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java @@ -40,11 +40,16 @@ public class SimpleJavaParameters extends SimpleProgramParameters { private Charset myCharset = CharsetToolkit.getDefaultSystemCharset(); private boolean myUseDynamicClasspath; private boolean myUseDynamicVMOptions; - + private String myJarPath; + public String getMainClass() { return myMainClass; } + public String getJarPath() { + return myJarPath; + } + /** * @return jdk used to launch the application. * If the instance of the JavaParameters is used to configure app server startup script, @@ -62,6 +67,9 @@ public class SimpleJavaParameters extends SimpleProgramParameters { public void setMainClass(@NonNls final String mainClass) { myMainClass = mainClass; } + public void setJarPath(@NonNls final String jarPath) { + myJarPath = jarPath; + } public PathsList getClassPath() { return myClassPath; diff --git a/platform/lang-api/src/com/intellij/execution/filters/ConsoleDependentFilterProvider.java b/platform/lang-api/src/com/intellij/execution/filters/ConsoleDependentFilterProvider.java new file mode 100644 index 000000000000..1b5f625b9b0e --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/filters/ConsoleDependentFilterProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2014 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.execution.filters; + +import com.intellij.execution.ui.ConsoleView; +import com.intellij.openapi.project.Project; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; + +public abstract class ConsoleDependentFilterProvider implements ConsoleFilterProvider { + @NotNull + public abstract Filter[] getDefaultFilters(@NotNull ConsoleView consoleView, @NotNull Project project, @NotNull GlobalSearchScope scope); + + @NotNull + @Override + public Filter[] getDefaultFilters(@NotNull Project project) { + return Filter.EMPTY_ARRAY; + } +}
\ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/execution/runners/AsyncGenericProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/AsyncGenericProgramRunner.java index ce7145adeaf9..6b63ec402320 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/AsyncGenericProgramRunner.java +++ b/platform/lang-api/src/com/intellij/execution/runners/AsyncGenericProgramRunner.java @@ -21,6 +21,7 @@ import com.intellij.execution.RunProfileStarter; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.configurations.RunnerSettings; import com.intellij.execution.ui.RunContentDescriptor; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.AsyncResult; import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; @@ -61,7 +62,17 @@ public abstract class AsyncGenericProgramRunner<Settings extends RunnerSettings> * @return RunProfileStarter async result */ @NotNull - protected abstract AsyncResult<RunProfileStarter> prepare(@NotNull ExecutionEnvironment environment, @NotNull RunProfileState state) throws ExecutionException; + protected AsyncResult<RunProfileStarter> prepare(@NotNull ExecutionEnvironment environment, @NotNull RunProfileState state) throws ExecutionException { + return prepare(environment.getProject(), environment, state); + } + + /** + * @deprecated override {@link #prepare(ExecutionEnvironment, com.intellij.execution.configurations.RunProfileState)} instead + */ + @Deprecated + protected AsyncResult<RunProfileStarter> prepare(@NotNull Project project, @NotNull ExecutionEnvironment environment, @NotNull RunProfileState state) throws ExecutionException { + throw new UnsupportedOperationException(); + } private static void startRunProfile(@NotNull ExecutionEnvironment environment, @NotNull RunProfileState state, diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java index b6c300c3f7e2..5a395ab5dd79 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java +++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java @@ -112,6 +112,10 @@ public class ExecutionUtil { UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { + if (project.isDisposed()) { + return; + } + ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project); if (toolWindowManager.canShowNotification(toolWindowId)) { //noinspection SSBasedInspection diff --git a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java index 60e7f03d54db..5a23ed45b1a9 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java +++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java @@ -15,11 +15,13 @@ */ package com.intellij.execution.ui; +import com.intellij.execution.DefaultExecutionResult; import com.intellij.execution.ExecutionResult; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.process.ProcessHandler; import com.intellij.ide.HelpIdProvider; import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.ui.content.Content; @@ -44,6 +46,8 @@ public class RunContentDescriptor implements Disposable { private Content myContent; private Runnable myRestarter; + @NotNull + private AnAction[] myRestartActions = AnAction.EMPTY_ARRAY; public RunContentDescriptor(@Nullable ExecutionConsole executionConsole, @Nullable ProcessHandler processHandler, @@ -66,7 +70,19 @@ public class RunContentDescriptor implements Disposable { } public RunContentDescriptor(@NotNull RunProfile profile, @NotNull ExecutionResult executionResult, @NotNull RunnerLayoutUi ui) { - this(executionResult.getExecutionConsole(), executionResult.getProcessHandler(), ui.getComponent(), profile.getName(), profile.getIcon()); + this(executionResult.getExecutionConsole(), executionResult.getProcessHandler(), ui.getComponent(), profile.getName(), + profile.getIcon()); + if (executionResult instanceof DefaultExecutionResult) { + myRestartActions = ((DefaultExecutionResult)executionResult).getRestartActions(); + } + } + + /** + * @return actions to restart or rerun + */ + @NotNull + public AnAction[] getRestartActions() { + return myRestartActions.clone(); } public ExecutionConsole getExecutionConsole() { @@ -81,6 +97,8 @@ public class RunContentDescriptor implements Disposable { } myComponent = null; myRestarter = null; + myProcessHandler = null; + myContent = null; } /** @@ -127,6 +145,7 @@ public class RunContentDescriptor implements Disposable { myContent = content; } + @SuppressWarnings("UnusedDeclaration") @Nullable @Deprecated /** diff --git a/platform/lang-api/src/com/intellij/find/FindModel.java b/platform/lang-api/src/com/intellij/find/FindModel.java index 5dafc2db8acf..d07187796872 100644 --- a/platform/lang-api/src/com/intellij/find/FindModel.java +++ b/platform/lang-api/src/com/intellij/find/FindModel.java @@ -107,9 +107,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable { if (!multiline) { initStringToFindNoMultiline(this, getStringToFind()); } - else { - setRegularExpressions(false); - } + isMultiline = multiline; notifyObservers(); } diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java index fddb2b2f50b7..861123ab7839 100644 --- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java +++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java @@ -25,6 +25,8 @@ import com.intellij.openapi.module.*; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectType; +import com.intellij.openapi.project.ProjectTypeService; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; @@ -56,12 +58,12 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { public static final ExtensionPointName<ModuleBuilderFactory> EP_NAME = ExtensionPointName.create("com.intellij.moduleBuilder"); private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.projectWizard.ModuleBuilder"); + private final Set<ModuleConfigurationUpdater> myUpdaters = new HashSet<ModuleConfigurationUpdater>(); + private final EventDispatcher<ModuleBuilderListener> myDispatcher = EventDispatcher.create(ModuleBuilderListener.class); protected Sdk myJdk; private String myName; @NonNls private String myModuleFilePath; private String myContentEntryPath; - private final Set<ModuleConfigurationUpdater> myUpdaters = new HashSet<ModuleConfigurationUpdater>(); - private final EventDispatcher<ModuleBuilderListener> myDispatcher = EventDispatcher.create(ModuleBuilderListener.class); @NotNull public static List<ModuleBuilder> getAllBuilders() { @@ -81,6 +83,17 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { }); } + public static void deleteModuleFile(String moduleFilePath) { + final File moduleFile = new File(moduleFilePath); + if (moduleFile.exists()) { + FileUtil.delete(moduleFile); + } + final VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(moduleFile); + if (file != null) { + file.refresh(false, false); + } + } + protected boolean isAvailable() { return true; } @@ -95,6 +108,11 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { } @Override + public void setName(String name) { + myName = acceptParameter(name); + } + + @Override @Nullable public String getBuilderId() { ModuleType moduleType = getModuleType(); @@ -167,24 +185,19 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { return Collections.emptyList(); } - @Override - public void setName(String name) { - myName = acceptParameter(name); - } - public String getModuleFilePath() { return myModuleFilePath; } - public void addModuleConfigurationUpdater(ModuleConfigurationUpdater updater) { - myUpdaters.add(updater); - } - @Override public void setModuleFilePath(@NonNls String path) { myModuleFilePath = acceptParameter(path); } + public void addModuleConfigurationUpdater(ModuleConfigurationUpdater updater) { + myUpdaters.add(updater); + } + @Nullable public String getContentEntryPath() { if (myContentEntryPath == null) { @@ -259,6 +272,7 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { updater.update(module, modifiableModel); } modifiableModel.commit(); + setProjectType(module); } private void onModuleInitialized(final Module module) { @@ -269,6 +283,17 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { public abstract ModuleType getModuleType(); + protected ProjectType getProjectType() { + return null; + } + + protected void setProjectType(Module module) { + ProjectType projectType = getProjectType(); + if (projectType != null && ProjectTypeService.getProjectType(module.getProject()) == null) { + ProjectTypeService.setProjectType(module.getProject(), projectType); + } + } + @NotNull public Module createAndCommitIfNeeded(@NotNull Project project, @Nullable ModifiableModuleModel model, boolean runFromProjectWizard) throws InvalidDataException, ConfigurationException, IOException, JDOMException, ModuleWithNameAlreadyExists { @@ -295,7 +320,6 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { return module; } - public void addListener(ModuleBuilderListener listener) { myDispatcher.addListener(listener); } @@ -340,17 +364,6 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { return null; } - public static void deleteModuleFile(String moduleFilePath) { - final File moduleFile = new File(moduleFilePath); - if (moduleFile.exists()) { - FileUtil.delete(moduleFile); - } - final VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(moduleFile); - if (file != null) { - file.refresh(false, false); - } - } - public Icon getBigIcon() { return getModuleType().getBigIcon(); } @@ -396,14 +409,14 @@ public abstract class ModuleBuilder extends AbstractModuleBuilder { myModuleFilePath = from.getModuleFilePath(); } - public void setModuleJdk(Sdk jdk) { - myJdk = jdk; - } - public Sdk getModuleJdk() { return myJdk; } + public void setModuleJdk(Sdk jdk) { + myJdk = jdk; + } + @NotNull public FrameworkRole getDefaultAcceptableRole() { return getModuleType().getDefaultAcceptableRole(); diff --git a/platform/lang-api/src/com/intellij/lang/documentation/DocumentationProviderEx.java b/platform/lang-api/src/com/intellij/lang/documentation/DocumentationProviderEx.java index 8b9143a0d995..9d7a10d6ba5e 100644 --- a/platform/lang-api/src/com/intellij/lang/documentation/DocumentationProviderEx.java +++ b/platform/lang-api/src/com/intellij/lang/documentation/DocumentationProviderEx.java @@ -29,6 +29,7 @@ import java.util.List; * @author peter */ public class DocumentationProviderEx implements DocumentationProvider { + @Nullable @Override public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) { return null; diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java index 4291e9b401bf..337909b318e5 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java @@ -247,7 +247,15 @@ public class JdkUtil { } final String mainClass = javaParameters.getMainClass(); - commandLine.addParameter(mainClass); + String jarPath = javaParameters.getJarPath(); + if (mainClass != null) { + commandLine.addParameter(mainClass); + } + else if (jarPath != null) { + commandLine.addParameter("-jar"); + commandLine.addParameter(jarPath); + } + commandLine.addParameters(javaParameters.getProgramParametersList().getList()); commandLine.setWorkDirectory(javaParameters.getWorkingDirectory()); @@ -260,7 +268,7 @@ public class JdkUtil { ParametersList parametersList) { commandLine.addParameters(parametersList.getList()); appendEncoding(javaParameters, commandLine, parametersList); - if (!parametersList.hasParameter("-classpath") && !parametersList.hasParameter("-cp")){ + if (!parametersList.hasParameter("-classpath") && !parametersList.hasParameter("-cp") && !javaParameters.getClassPath().getPathList().isEmpty()){ commandLine.addParameter("-classpath"); commandLine.addParameter(javaParameters.getClassPath().getPathsString()); } diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java index ecebb9db73f3..ae9f0142f246 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java @@ -23,7 +23,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; -import com.intellij.openapi.fileChooser.FileChooserDialog; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; @@ -67,7 +66,6 @@ public class PathEditor { public PathEditor(final FileChooserDescriptor descriptor) { myDescriptor = descriptor; - myDescriptor.putUserData(FileChooserDialog.PREFER_LAST_OVER_TO_SELECT, Boolean.TRUE); myModel = createListModel(); } @@ -176,12 +174,8 @@ public class PathEditor { } protected VirtualFile[] doAdd() { - VirtualFile baseDir = myAddBaseDir; Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(myPanel)); - if (baseDir == null && project != null) { - baseDir = project.getBaseDir(); - } - VirtualFile[] files = FileChooser.chooseFiles(myDescriptor, myPanel, project, baseDir); + VirtualFile[] files = FileChooser.chooseFiles(myDescriptor, myPanel, project, myAddBaseDir); files = adjustAddedFileSet(myPanel, files); List<VirtualFile> added = new ArrayList<VirtualFile>(files.length); for (VirtualFile vFile : files) { diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java index 290078e39aa9..2ef2c998b3b4 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java @@ -214,6 +214,7 @@ public interface CodeStyleSettingsCustomizable { String WRAPPING_KEEP = ApplicationBundle.message("wrapping.keep.when.reformatting"); String WRAPPING_BRACES = ApplicationBundle.message("wrapping.brace.placement"); + String WRAPPING_COMMENTS = ApplicationBundle.message("wrapping.comments"); String WRAPPING_METHOD_PARAMETERS = ApplicationBundle.message("wrapping.method.parameters"); String WRAPPING_METHOD_PARENTHESES = ApplicationBundle.message("wrapping.method.parentheses"); String WRAPPING_METHOD_ARGUMENTS_WRAPPING = ApplicationBundle.message("wrapping.method.arguments"); diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java index 299d17215fdf..fa284c8fd33c 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -21,7 +21,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.util.*; import com.intellij.psi.codeStyle.arrangement.ArrangementSettings; import com.intellij.psi.codeStyle.arrangement.ArrangementUtil; -import com.intellij.util.containers.HashSet; +import com.intellij.util.ReflectionUtil; import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; import com.intellij.util.xmlb.XmlSerializer; import org.intellij.lang.annotations.MagicConstant; @@ -31,8 +31,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Arrays; import java.util.Set; /** @@ -155,63 +153,20 @@ public class CommonCodeStyleSettings { protected static void copyPublicFields(Object from, Object to) { assert from != to; - copyFields(to.getClass().getFields(), from, to); + ReflectionUtil.copyFields(to.getClass().getFields(), from, to); } void copyNonDefaultValuesFrom(CommonCodeStyleSettings from) { CommonCodeStyleSettings defaultSettings = new CommonCodeStyleSettings(null); PARENT_SETTINGS_INSTALLED = - copyFields(getClass().getFields(), from, this, new SupportedFieldsDiffFilter(from, getSupportedFields(), defaultSettings) { - @Override - public boolean isAccept(@NotNull Field field) { - if ("RIGHT_MARGIN".equals(field.getName())) return false; // Never copy RIGHT_MARGIN, it is inherited automatically if -1 - return super.isAccept(field); - } - }); - } - - private static void copyFields(Field[] fields, Object from, Object to) { - copyFields(fields, from, to, null); - } - - private static boolean copyFields(Field[] fields, Object from, Object to, @Nullable DifferenceFilter diffFilter) { - Set<Field> sourceFields = new HashSet<Field>(Arrays.asList(from.getClass().getFields())); - boolean valuesChanged = false; - for (Field field : fields) { - if (sourceFields.contains(field)) { - if (isPublic(field) && !isFinal(field)) { - try { - if (diffFilter == null || diffFilter.isAccept(field)) { - copyFieldValue(from, to, field); - valuesChanged = true; - } - } - catch (Exception e) { - throw new RuntimeException(e); + ReflectionUtil + .copyFields(getClass().getFields(), from, this, new SupportedFieldsDiffFilter(from, getSupportedFields(), defaultSettings) { + @Override + public boolean isAccept(@NotNull Field field) { + if ("RIGHT_MARGIN".equals(field.getName())) return false; // Never copy RIGHT_MARGIN, it is inherited automatically if -1 + return super.isAccept(field); } - } - } - } - return valuesChanged; - } - - private static void copyFieldValue(final Object from, Object to, final Field field) - throws IllegalAccessException { - Class<?> fieldType = field.getType(); - if (fieldType.isPrimitive() || fieldType.equals(String.class)) { - field.set(to, field.get(from)); - } - else { - throw new RuntimeException("Field not copied " + field.getName()); - } - } - - private static boolean isPublic(final Field field) { - return (field.getModifiers() & Modifier.PUBLIC) != 0; - } - - private static boolean isFinal(final Field field) { - return (field.getModifiers() & Modifier.FINAL) != 0; + }); } @Nullable diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java new file mode 100644 index 000000000000..527ee9e79a49 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java @@ -0,0 +1,106 @@ +/* + * Copyright 2000-2014 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.psi.codeStyle.autodetect; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +import static com.intellij.psi.codeStyle.CommonCodeStyleSettings.*; + +public class IndentOptionsDetector { + private static Logger LOG = Logger.getInstance("#com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptionsDetector"); + + private static final double RATE_THRESHOLD = 0.8; + private static final int MIN_LINES_THRESHOLD = 50; + private static final int MAX_INDENT_TO_DETECT = 8; + + private final PsiFile myFile; + private final Project myProject; + private final Document myDocument; + + public IndentOptionsDetector(@NotNull PsiFile file) { + myFile = file; + myProject = file.getProject(); + myDocument = PsiDocumentManager.getInstance(myProject).getDocument(myFile); + } + + @NotNull + public IndentOptions getIndentOptions() { + IndentOptions indentOptions = (IndentOptions)CodeStyleSettingsManager.getSettings(myProject).getIndentOptions(myFile.getFileType()).clone(); + + if (myDocument != null) { + List<LineIndentInfo> linesInfo = new LineIndentInfoBuilder(myDocument.getCharsSequence()).build(); + IndentUsageStatistics stats = new IndentUsageStatisticsImpl(linesInfo); + adjustIndentOptions(indentOptions, stats); + } + + return indentOptions; + } + + private void adjustIndentOptions(@NotNull IndentOptions indentOptions, @NotNull IndentUsageStatistics stats) { + int linesWithTabs = stats.getTotalLinesWithLeadingTabs(); + int linesWithWhiteSpaceIndent = stats.getTotalLinesWithLeadingSpaces(); + + int totalLines = linesWithTabs + linesWithWhiteSpaceIndent; + double lineWithTabsRate = (double)linesWithTabs / totalLines; + + if (linesWithTabs > MIN_LINES_THRESHOLD && lineWithTabsRate > RATE_THRESHOLD) { + if (!indentOptions.USE_TAB_CHARACTER) { + indentOptions.USE_TAB_CHARACTER = true; + LOG.info("Detected tab usage in" + myFile); + } + } + else if (linesWithWhiteSpaceIndent > MIN_LINES_THRESHOLD && (1 - lineWithTabsRate) > RATE_THRESHOLD) { + int newIndentSize = getPositiveIndentSize(stats); + if (newIndentSize > 0 && indentOptions.INDENT_SIZE != newIndentSize) { + indentOptions.INDENT_SIZE = newIndentSize; + LOG.info("Detected indent size: " + newIndentSize + " for file " + myFile); + } + } + } + + private static int getPositiveIndentSize(@NotNull IndentUsageStatistics stats) { + int totalIndentSizesDetected = stats.getTotalIndentSizesDetected(); + if (totalIndentSizesDetected == 0) return -1; + + IndentUsageInfo maxUsedIndentInfo = stats.getKMostUsedIndentInfo(0); + int maxUsedIndentSize = maxUsedIndentInfo.getIndentSize(); + + if (maxUsedIndentSize == 0) { + if (totalIndentSizesDetected < 1) return -1; + + maxUsedIndentInfo = stats.getKMostUsedIndentInfo(1); + maxUsedIndentSize = maxUsedIndentInfo.getIndentSize(); + } + + if (maxUsedIndentSize <= MAX_INDENT_TO_DETECT) { + int totalUsagesWithoutZeroIndent = stats.getTotalLinesWithLeadingSpaces() - stats.getTimesIndentUsed(0); + double usageRate = (double)maxUsedIndentInfo.getTimesUsed() / totalUsagesWithoutZeroIndent; + if (usageRate > RATE_THRESHOLD) { + return maxUsedIndentSize; + } + } + + return -1; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageInfo.java new file mode 100644 index 000000000000..a600483a07a6 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageInfo.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2014 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.psi.codeStyle.autodetect; + +public class IndentUsageInfo { + private final int indentSize; + private final int timesUsed; + + public IndentUsageInfo(int indentSize, int timesUsed) { + this.indentSize = indentSize; + this.timesUsed = timesUsed; + } + + public int getIndentSize() { + return indentSize; + } + + public int getTimesUsed() { + return timesUsed; + } + + @Override + public String toString() { + return "indent: " + indentSize + ", used " + timesUsed; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java new file mode 100644 index 000000000000..7e3bee7221da --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2014 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.psi.codeStyle.autodetect; + +public interface IndentUsageStatistics { + + int getTotalLinesWithLeadingTabs(); + + int getTotalLinesWithLeadingSpaces(); + + IndentUsageInfo getKMostUsedIndentInfo(int k); + + int getTotalIndentSizesDetected(); + + int getTimesIndentUsed(int indent); + +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java new file mode 100644 index 000000000000..99de432f101d --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java @@ -0,0 +1,149 @@ +/* + * Copyright 2000-2014 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.psi.codeStyle.autodetect; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Stack; +import gnu.trove.TIntIntHashMap; +import gnu.trove.TIntIntIterator; +import org.jetbrains.annotations.NotNull; + +import java.util.Comparator; +import java.util.List; + +public class IndentUsageStatisticsImpl implements IndentUsageStatistics { + private static final Comparator<IndentUsageInfo> DECREASING_ORDER = new Comparator<IndentUsageInfo>() { + @Override + public int compare(@NotNull IndentUsageInfo o1, @NotNull IndentUsageInfo o2) { + return o1.getTimesUsed() < o2.getTimesUsed() ? 1 : o1.getTimesUsed() == o2.getTimesUsed() ? 0 : -1; + } + }; + + private List<LineIndentInfo> myLineInfos; + + private int myPreviousLineIndent; + private int myPreviousRelativeIndent; + + private int myTotalLinesWithTabs = 0; + private int myTotalLinesWithWhiteSpaces = 0; + + private TIntIntHashMap myIndentToUsagesMap = new TIntIntHashMap(); + private List<IndentUsageInfo> myIndentUsages = ContainerUtil.newArrayList(); + private Stack<IndentData> myParentIndents = ContainerUtil.newStack(new IndentData(0, 0)); + + public IndentUsageStatisticsImpl(@NotNull List<LineIndentInfo> lineInfos) { + myLineInfos = lineInfos; + buildIndentToUsagesMap(); + myIndentUsages = toIndentUsageList(myIndentToUsagesMap); + ContainerUtil.sort(myIndentUsages, DECREASING_ORDER); + } + + @NotNull + private static List<IndentUsageInfo> toIndentUsageList(@NotNull TIntIntHashMap indentToUsages) { + List<IndentUsageInfo> indentUsageInfos = ContainerUtil.newArrayList(); + TIntIntIterator it = indentToUsages.iterator(); + while (it.hasNext()) { + it.advance(); + indentUsageInfos.add(new IndentUsageInfo(it.key(), it.value())); + } + return indentUsageInfos; + } + + public void buildIndentToUsagesMap() { + myPreviousLineIndent = 0; + myPreviousRelativeIndent = 0; + + for (LineIndentInfo lineInfo : myLineInfos) { + if (lineInfo.isLineWithTabs()) { + myTotalLinesWithTabs++; + } + else if (lineInfo.isLineWithWhiteSpaceIndent()) { + handleWhiteSpaceIndent(lineInfo.getIndentSize()); + } + } + } + + @NotNull + private IndentData findParentIndent(int indent) { + while (myParentIndents.size() != 1 && myParentIndents.peek().indent > indent) { + myParentIndents.pop(); + } + return myParentIndents.peek(); + } + + private void handleWhiteSpaceIndent(int currentIndent) { + int relativeIndent = currentIndent - myPreviousLineIndent; + if (relativeIndent < 0) { + IndentData indentData = findParentIndent(currentIndent); + myPreviousLineIndent = indentData.indent; + myPreviousRelativeIndent = indentData.relativeIndent; + relativeIndent = currentIndent - myPreviousLineIndent; + } + + if (relativeIndent == 0) { + relativeIndent = myPreviousRelativeIndent; + } + else { + myParentIndents.push(new IndentData(currentIndent, relativeIndent)); + } + + increaseIndentUsage(relativeIndent); + + myPreviousRelativeIndent = relativeIndent; + myPreviousLineIndent = currentIndent; + myTotalLinesWithWhiteSpaces++; + } + + private void increaseIndentUsage(int relativeIndent) { + int timesUsed = myIndentToUsagesMap.get(relativeIndent); + myIndentToUsagesMap.put(relativeIndent, ++timesUsed); + } + + @Override + public int getTotalLinesWithLeadingTabs() { + return myTotalLinesWithTabs; + } + + @Override + public int getTotalLinesWithLeadingSpaces() { + return myTotalLinesWithWhiteSpaces; + } + + @Override + public IndentUsageInfo getKMostUsedIndentInfo(int k) { + return myIndentUsages.get(k); + } + + @Override + public int getTimesIndentUsed(int indent) { + return myIndentToUsagesMap.get(indent); + } + + @Override + public int getTotalIndentSizesDetected() { + return myIndentToUsagesMap.size(); + } + + private static class IndentData { + public final int indent; + public final int relativeIndent; + + public IndentData(int indent, int relativeIndent) { + this.indent = indent; + this.relativeIndent = relativeIndent; + } + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java new file mode 100644 index 000000000000..d85a4cbcaa0e --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2014 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.psi.codeStyle.autodetect; + +import org.jetbrains.annotations.NotNull; + +public class LineIndentInfo { + public static final LineIndentInfo EMPTY_LINE = new LineIndentInfo(LineType.EMPTY_LINE, -1); + public static final LineIndentInfo LINE_WITH_COMMENT = new LineIndentInfo(LineType.LINE_WITH_COMMENT, -1); + public static final LineIndentInfo LINE_WITH_TABS = new LineIndentInfo(LineType.LINE_WITH_TABS, -1); + + private final int myIndentSize; + private final LineType myType; + + private LineIndentInfo(@NotNull LineType type, int indentSize) { + myType = type; + myIndentSize = indentSize; + } + + @NotNull + public static LineIndentInfo newWhiteSpaceIndent(int indentSize) { + return new LineIndentInfo(LineType.LINE_WITH_WHITESPACE_INDENT, indentSize); + } + + public int getIndentSize() { + return myIndentSize; + } + + public boolean isLineWithWhiteSpaceIndent() { + return myType == LineType.LINE_WITH_WHITESPACE_INDENT; + } + + public boolean isLineWithTabs() { + return myType == LineType.LINE_WITH_TABS; + } + + private enum LineType { + EMPTY_LINE, + LINE_WITH_COMMENT, + LINE_WITH_TABS, + LINE_WITH_WHITESPACE_INDENT + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java new file mode 100644 index 000000000000..8efbbc495750 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2014 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.psi.codeStyle.autodetect; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class LineIndentInfoBuilder { + private static final int MAX_LINES_TO_PROCESS = 500; + + private final CharSequence myText; + private final int myLength; + + public LineIndentInfoBuilder(@NotNull CharSequence text) { + myText = text; + myLength = text.length(); + } + + @NotNull + public List<LineIndentInfo> build() { + List<LineIndentInfo> lineIndentInfos = ContainerUtil.newArrayList(); + + int lineStartOffset = 0; + int currentLine = 0; + + while (lineStartOffset < myText.length() && currentLine < MAX_LINES_TO_PROCESS) { + int lineEndOffset = getLineEndOffset(lineStartOffset); + int textStartOffset = CharArrayUtil.shiftForward(myText, lineStartOffset, lineEndOffset, " \t"); + + if (textStartOffset != lineEndOffset) { + lineIndentInfos.add(createInfoFromWhiteSpaceRange(lineStartOffset, textStartOffset)); + } else { + lineIndentInfos.add(LineIndentInfo.EMPTY_LINE); + } + + lineStartOffset = lineEndOffset + 1; + currentLine++; + } + + return lineIndentInfos; + } + + @NotNull + private LineIndentInfo createInfoFromWhiteSpaceRange(int lineStartOffset, int textStartOffset) { + if (myText.charAt(textStartOffset) == '*') { + return LineIndentInfo.LINE_WITH_COMMENT; + } + else if (CharArrayUtil.indexOf(myText, "\t", lineStartOffset, textStartOffset) > 0) { + return LineIndentInfo.LINE_WITH_TABS; + } + else { + int indentSize = textStartOffset - lineStartOffset; + return LineIndentInfo.newWhiteSpaceIndent(indentSize); + } + } + + private int getLineEndOffset(int lineStartOffset) { + int lineEndOffset = CharArrayUtil.indexOf(myText, "\n", lineStartOffset, myLength); + if (lineEndOffset < 0) { + lineEndOffset = myText.length(); + } + return lineEndOffset; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java index 4565832c310b..b63ee1d6ab2d 100644 --- a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java +++ b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java @@ -40,7 +40,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; import java.util.*; +import java.util.List; public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.PsiUtilBase"); @@ -235,6 +237,9 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil { */ @Nullable public static Editor findEditor(@NotNull PsiElement element) { + if (!EventQueue.isDispatchThread()) { + LOG.warn("Invoke findEditor() from EDT only. Otherwise, it causes deadlocks."); + } PsiFile psiFile = element.getContainingFile(); VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element); if (virtualFile == null) { |