diff --git a/.idea/libraries/Snappy_Java.xml b/.idea/libraries/Snappy_Java.xml new file mode 100644 index 000000000000..85b426fb3a0c --- /dev/null +++ b/.idea/libraries/Snappy_Java.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java index dbc64d0382de..f0befa3c0287 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java @@ -23,7 +23,7 @@ import com.intellij.lang.ParserDefinition; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.tree.IElementType; import com.intellij.util.IncorrectOperationException; import org.intellij.lang.regexp.RegExpLanguage; @@ -76,7 +76,7 @@ public abstract class RegExpElementImpl extends ASTWrapperPsiElement implements } public final String getUnescapedText() { - if (InjectedLanguageFacadeImpl.isInInjectedLanguagePrefixSuffix(this)) { + if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(this)) { // do not attempt to decode text if PsiElement is part of prefix/suffix return getText(); } diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index 29b981ef038e..499532977c06 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -181,7 +181,7 @@ libraryLicense(name: "Apache Commons HTTPCore", libraryName: "httpcore-4.1.jar", url: "http://hc.apache.org/httpcomponents-core-ga/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Antlr", libraryName: "antlr.jar", version: "3.1.3", license: "BSD", url: "http://www.antlr.org", licenseUrl: "http://www.antlr.org/license.html") -libraryLicense(name: "Guava", version: "R8", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://ant.apache.org/license.html") +libraryLicense(name: "Guava", version: "12.0", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://ant.apache.org/license.html") libraryLicense(name: "Groovy", version: "1.7.3", license: "Apache 2.0", url: "http://groovy.codehaus.org/") libraryLicense(name: "Gson", libraryName: "gson", license: "Apache 2.0", url: "http://code.google.com/p/google-gson/") libraryLicense(name: "ini4j", libraryName: "ini4j-0.5.2-patched", version: "0.5.2 (with a patch by JetBrains)", license: "Apache 2.0", url: "http://ini4j.sourceforge.net/", attachedTo: "git4idea") @@ -238,6 +238,7 @@ libraryLicense(name: "YourKit Java Profiler", libraryName: "yjp-controller-api-r libraryLicense(name: "protobuf", version: "2.3.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "http://code.google.com/p/protobuf/source/browse/trunk/COPYING.txt?r=367") libraryLicense(name: "Netty", libraryName: "Netty", version: "3.3.1", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Kryo", libraryName: "Kryo", version: "1.04", license: "New BSD License", url: "http://code.google.com/p/kryo/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php") +libraryLicense(name: "Snappy-Java", libraryName: "Snappy-Java", version: "1.0.4.1", license: "Apache 2.0", url: "http://code.google.com/p/snappy-java/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") jetbrainsLibrary("JPS") jetbrainsLibrary("Maven Embedder") jetbrainsLibrary("tcServiceMessages") diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png index d7fbd05ec578..f4962130748a 100644 Binary files a/community-resources/src/idea_community_about.png and b/community-resources/src/idea_community_about.png differ diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png index e5f9efcb90e2..71d6845b66fc 100644 Binary files a/community-resources/src/idea_community_logo.png and b/community-resources/src/idea_community_logo.png differ diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index 8363e6278bf1..5d13be23f351 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -81,7 +81,10 @@ import com.intellij.packaging.impl.compiler.ArtifactCompileScope; import com.intellij.packaging.impl.compiler.ArtifactCompilerUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiDocumentManager; -import com.intellij.util.*; +import com.intellij.util.Chunk; +import com.intellij.util.Function; +import com.intellij.util.StringBuilderSpinAllocator; +import com.intellij.util.ThrowableRunnable; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; @@ -628,7 +631,6 @@ public class CompileDriver { } - public static final Key COMPILATION_START_TIMESTAMP = Key.create("COMPILATION_START_TIMESTAMP"); public static final Key COMPILE_SERVER_BUILD_STATUS = Key.create("COMPILE_SERVER_BUILD_STATUS"); private void startup(final CompileScope scope, @@ -658,7 +660,6 @@ public class CompileDriver { final DependencyCache dependencyCache = useExtProcessBuild ? null: createDependencyCache(); final CompileContextImpl compileContext = new CompileContextImpl(myProject, compileTask, scope, dependencyCache, !isRebuild && !forceCompile, isRebuild); - compileContext.putUserData(COMPILATION_START_TIMESTAMP, LocalTimeCounter.currentTime()); if (!useExtProcessBuild) { for (Map.Entry, Pair> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) { @@ -889,12 +890,12 @@ public class CompileDriver { errorCount = compileContext.getMessageCount(CompilerMessageCategory.ERROR); warningCount = compileContext.getMessageCount(CompilerMessageCategory.WARNING); if (!myProject.isDisposed()) { - final String statusMessage = createStatusMessage(_status, warningCount, errorCount); + final String statusMessage = createStatusMessage(_status, warningCount, errorCount, duration); final MessageType messageType = errorCount > 0 ? MessageType.ERROR : warningCount > 0 ? MessageType.WARNING : MessageType.INFO; if (duration > ONE_MINUTE_MS) { ToolWindowManager.getInstance(myProject).notifyByBalloon(ToolWindowId.MESSAGES_WINDOW, messageType, statusMessage); } - CompilerManager.NOTIFICATION_GROUP.createNotification(_status == ExitStatus.UP_TO_DATE ? "Compilation: all files are up to date" : statusMessage, messageType).notify(myProject); + CompilerManager.NOTIFICATION_GROUP.createNotification(statusMessage, messageType).notify(myProject); if (_status != ExitStatus.UP_TO_DATE && compileContext.getMessageCount(null) > 0) { compileContext.addMessage(CompilerMessageCategory.INFORMATION, statusMessage, null, -1, -1); } @@ -932,19 +933,35 @@ public class CompileDriver { } } - private static String createStatusMessage(final ExitStatus status, final int warningCount, final int errorCount) { + private static String createStatusMessage(final ExitStatus status, final int warningCount, final int errorCount, long duration) { + String message; if (status == ExitStatus.CANCELLED) { - return CompilerBundle.message("status.compilation.aborted"); + message = CompilerBundle.message("status.compilation.aborted"); } - if (status == ExitStatus.UP_TO_DATE) { - return CompilerBundle.message("status.all.up.to.date"); + else if (status == ExitStatus.UP_TO_DATE) { + message = CompilerBundle.message("status.all.up.to.date"); } - if (status == ExitStatus.SUCCESS) { - return warningCount > 0 - ? CompilerBundle.message("status.compilation.completed.successfully.with.warnings", warningCount) - : CompilerBundle.message("status.compilation.completed.successfully"); + else { + if (status == ExitStatus.SUCCESS) { + message = warningCount > 0 + ? CompilerBundle.message("status.compilation.completed.successfully.with.warnings", warningCount) + : CompilerBundle.message("status.compilation.completed.successfully"); + } + else { + message = CompilerBundle.message("status.compilation.completed.successfully.with.warnings.and.errors", errorCount, warningCount); + } + message = message + " in " + formatDuration(duration); } - return CompilerBundle.message("status.compilation.completed.successfully.with.warnings.and.errors", errorCount, warningCount); + return message; + } + + public static String formatDuration(long duration) { + final long minutes = duration / 60000; + final long seconds = (duration % 60000) / 1000; + if (minutes > 0L) { + return minutes + " min " + seconds + " sec"; + } + return seconds + " sec"; } private ExitStatus doCompile(final CompileContextEx context, boolean isRebuild, final boolean forceCompile, final boolean onlyCheckStatus) { diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form b/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form index 2111e6f4d29f..0a206e0e5a1a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form @@ -82,7 +82,7 @@ - + @@ -98,7 +98,7 @@ - + diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java index 4e1093d6fa37..0715ae03dd4f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java @@ -18,20 +18,21 @@ package com.intellij.compiler.options; import com.intellij.compiler.*; import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor; import com.intellij.compiler.server.BuildManager; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.StringTokenizer; public class CompilerUIConfigurable implements SearchableConfigurable, Configurable.NoScroll { @@ -49,10 +50,6 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura public CompilerUIConfigurable(final Project project) { myProject = project; - final boolean isServerOptionEnabled = Registry.is("compiler.out-of-process.build.enabled") || ApplicationManager.getApplication().isInternal(); - myCbUseCompileServer.setVisible(isServerOptionEnabled); - myCbMakeProjectOnSave.setVisible(isServerOptionEnabled); - myCbAllowAutomakeWhileRunningApplication.setVisible(isServerOptionEnabled); myPatternLegendLabel.setText("" + "Use ; to separate patterns and ! to negate a pattern. " + @@ -60,6 +57,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura "/ — path separator; /**/ — any number of directories; " + "<dir_name>:<pattern> — restrict to source roots with the specified name" + ""); + myCbAllowAutomakeWhileRunningApplication.setVisible(false); myCbUseCompileServer.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { @@ -103,7 +101,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura final CompilerWorkspaceConfiguration workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(myProject); workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR = myCbAutoShowFirstError.isSelected(); workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY = myCbClearOutputDirectory.isSelected(); - boolean wasUsing = workspaceConfiguration.USE_COMPILE_SERVER; + boolean wasUsingExternalMake = workspaceConfiguration.USE_COMPILE_SERVER; workspaceConfiguration.USE_COMPILE_SERVER = myCbUseCompileServer.isSelected(); workspaceConfiguration.MAKE_PROJECT_ON_SAVE = myCbMakeProjectOnSave.isSelected(); workspaceConfiguration.ALLOW_AUTOMAKE_WHILE_RUNNING_APPLICATION = myCbAllowAutomakeWhileRunningApplication.isSelected(); @@ -115,14 +113,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura // this will schedule for compilation all files that might become compilable after resource patterns' changing final TranslatingCompilerFilesMonitor monitor = TranslatingCompilerFilesMonitor.getInstance(); - if (!workspaceConfiguration.USE_COMPILE_SERVER) { - if (wasUsing) { - CompileServerManager.getInstance().shutdownServer(); - monitor.watchProject(myProject); - monitor.scanSourcesForCompilableFiles(myProject); - } - } - else { + if (workspaceConfiguration.USE_COMPILE_SERVER) { monitor.suspendProject(myProject); SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -131,6 +122,26 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura } }); } + else { + // use old make + if (wasUsingExternalMake) { + CompileServerManager.getInstance().shutdownServer(); + monitor.watchProject(myProject); + monitor.scanSourcesForCompilableFiles(myProject); + if (!myProject.isDefault()) { + final File buildSystem = BuildManager.getInstance().getBuildSystemDirectory(); + final File[] subdirs = buildSystem.listFiles(); + if (subdirs != null) { + final String prefix = myProject.getName().toLowerCase(Locale.US) + "_"; + for (File subdir : subdirs) { + if (subdir.getName().startsWith(prefix)) { + FileUtil.asyncDelete(subdir); + } + } + } + } + } + } } private static void applyResourcePatterns(String extensionString, final CompilerConfigurationImpl configuration) @@ -170,7 +181,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura isModified |= ComparingUtils.isModified(myCbAutoShowFirstError, workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR); isModified |= ComparingUtils.isModified(myCbUseCompileServer, workspaceConfiguration.USE_COMPILE_SERVER); isModified |= ComparingUtils.isModified(myCbMakeProjectOnSave, workspaceConfiguration.MAKE_PROJECT_ON_SAVE); - isModified |= ComparingUtils.isModified(myCbAllowAutomakeWhileRunningApplication, workspaceConfiguration.ALLOW_AUTOMAKE_WHILE_RUNNING_APPLICATION); + isModified |= ComparingUtils.isModified(myCbAllowAutomakeWhileRunningApplication, workspaceConfiguration.allowAutoMakeWhileRunningApplication()); final CompilerConfigurationImpl compilerConfiguration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject); isModified |= ComparingUtils.isModified(myCbAssertNotNull, compilerConfiguration.isAddNotNullAssertions()); diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index f69a80666049..4bc8b412687a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -294,7 +294,7 @@ public class BuildManager implements ApplicationComponent{ if (!config.useOutOfProcessBuild() || !config.MAKE_PROJECT_ON_SAVE) { continue; } - if (!config.ALLOW_AUTOMAKE_WHILE_RUNNING_APPLICATION) { + if (!config.allowAutoMakeWhileRunningApplication()) { final RunContentManager contentManager = ExecutionManager.getInstance(project).getContentManager(); boolean hasRunningProcesses = false; for (RunContentDescriptor descriptor : contentManager.getAllDescriptors()) { @@ -746,7 +746,7 @@ public class BuildManager implements ApplicationComponent{ cmdLine.addParameter(Integer.toString(port)); cmdLine.addParameter(sessionId.toString()); - final File workDirectory = new File(mySystemDirectory, SYSTEM_ROOT); + final File workDirectory = getBuildSystemDirectory(); workDirectory.mkdirs(); ensureLogConfigExists(workDirectory); @@ -757,6 +757,10 @@ public class BuildManager implements ApplicationComponent{ return cmdLine.createProcess(); } + public File getBuildSystemDirectory() { + return new File(mySystemDirectory, SYSTEM_ROOT); + } + private static int getMinorVersion(String vs) { final int dashIndex = vs.lastIndexOf('_'); if (dashIndex >= 0) { diff --git a/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java b/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java index 9eb810438be9..8e11249c8d08 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java +++ b/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java @@ -58,4 +58,7 @@ public class CompilerWorkspaceConfiguration implements PersistentStateComponent< public static boolean useServerlessOutOfProcessBuild() { return true/*!Registry.is("compiler.out-of-process.as-server")*/; } + public boolean allowAutoMakeWhileRunningApplication() { + return false;/*ALLOW_AUTOMAKE_WHILE_RUNNING_APPLICATION*/ + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java index 8ba45abd66c3..04a2e63038ba 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java @@ -369,18 +369,20 @@ public abstract class BreakpointPropertiesPanel { insert(myClassFiltersFieldPanel, myClassFiltersField); DebuggerUIUtil.enableEditorOnCheck(myLogExpressionCheckBox, myLogExpressionCombo); - ActionListener listener = new ActionListener() { + ActionListener updateListener = new ActionListener() { public void actionPerformed(ActionEvent e) { updateCheckboxes(); } }; - myPassCountCheckbox.addActionListener(listener); - myInstanceFiltersCheckBox.addActionListener(listener); - myClassFiltersCheckBox.addActionListener(listener); + myPassCountCheckbox.addActionListener(updateListener); + myInstanceFiltersCheckBox.addActionListener(updateListener); + myClassFiltersCheckBox.addActionListener(updateListener); + myConditionCheckbox.addActionListener(updateListener); DebuggerUIUtil.focusEditorOnCheck(myPassCountCheckbox, myPassCountField); DebuggerUIUtil.focusEditorOnCheck(myLogExpressionCheckBox, myLogExpressionCombo); DebuggerUIUtil.focusEditorOnCheck(myInstanceFiltersCheckBox, myInstanceFiltersField.getTextField()); DebuggerUIUtil.focusEditorOnCheck(myClassFiltersCheckBox, myClassFiltersField.getTextField()); + DebuggerUIUtil.focusEditorOnCheck(myConditionCheckbox, myConditionCombo); IJSwingUtilities.adjustComponentsOnMac(mySuspendJBCheckBox); IJSwingUtilities.adjustComponentsOnMac(myLogExpressionCheckBox); @@ -873,7 +875,7 @@ public abstract class BreakpointPropertiesPanel { break; } } - if(selected != null || !myConditionCombo.getText().isEmpty()){ + if(selected != null || !myConditionCheckbox.isSelected()){ myPassCountCheckbox.setEnabled(false); } else { myPassCountCheckbox.setEnabled(true); @@ -886,8 +888,8 @@ public abstract class BreakpointPropertiesPanel { myPassCountField.setEditable(myPassCountCheckbox.isSelected()); myPassCountField.setEnabled (myPassCountCheckbox.isSelected()); - myConditionCombo.setEnabled(true); - myConditionMagnifierButton.setEnabled(true); + myConditionCombo.setEnabled(myConditionCheckbox.isSelected()); + myConditionMagnifierButton.setEnabled(myConditionCheckbox.isSelected()); myInstanceFiltersField.setEnabled(myInstanceFiltersCheckBox.isSelected()); myInstanceFiltersField.getTextField().setEditable(myInstanceFiltersCheckBox.isSelected()); diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index a4718817a404..3947e5c6d0f8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -136,7 +136,7 @@ public class ExpectedTypesProvider { public static PsiType[] processExpectedTypes(@NotNull ExpectedTypeInfo[] infos, @NotNull PsiTypeVisitor visitor, @NotNull Project project) { - Set set = new LinkedHashSet(); + LinkedHashSet set = new LinkedHashSet(); for (ExpectedTypeInfo info : infos) { ExpectedTypeInfoImpl infoImpl = (ExpectedTypeInfoImpl)info; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index d96b05aaf471..b4abb4ee4e7d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -105,11 +105,10 @@ public class ConstructorInsertHandler implements InsertHandler() { - public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext matchingContext, @NotNull final CompletionResultSet _result) { - if (shouldShowSecondSmartCompletionHint(parameters) && - CompletionUtil.shouldShowFeature(parameters, CodeCompletionFeatures.SECOND_CLASS_NAME_COMPLETION)) { - CompletionService.getCompletionService().setAdvertisementText(CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION))); + @Override + public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet _result) { + if (parameters.isExtendedCompletion()) { + CompletionResultSet result = _result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters)); + addAllClasses(parameters, parameters.getInvocationCount() <= 1, + JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer() { + @Override + public void consume(LookupElement element) { + _result.addElement(element); } - - CompletionResultSet result = _result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters)); - addAllClasses(parameters, parameters.getInvocationCount() <= 1, - JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer() { - @Override - public void consume(LookupElement element) { - _result.addElement(element); - } - }); - } - }); + }); + } } public static void addAllClasses(CompletionParameters parameters, @@ -179,7 +172,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { return LangBundle.message("completion.no.suggestions") + "; " + StringUtil.decapitalize( - CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION))); + CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CODE_COMPLETION))); } return null; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 6e0274599cf1..f76488c5d4b9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -257,7 +257,10 @@ public class JavaCompletionContributor extends CompletionContributor { public static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) { - if (!isClassNamePossible(parameters.getPosition()) || !mayStartClassName(result)) return; + if (!isClassNamePossible(parameters.getPosition()) && parameters.getInvocationCount() <= 1 || + !mayStartClassName(result)) { + return; + } if (mayShowAllClasses(parameters)) { JavaClassNameCompletionContributor.addAllClasses(parameters, parameters.getInvocationCount() <= 2, result.getPrefixMatcher(), new Consumer() { @@ -471,9 +474,9 @@ public class JavaCompletionContributor extends CompletionContributor { PsiElement position = parameters.getPosition(); if (psiElement().withParent(psiReferenceExpression().withFirstChild(psiReferenceExpression().referencing(psiClass()))).accepts(position)) { if (CompletionUtil.shouldShowFeature(parameters, JavaCompletionFeatures.GLOBAL_MEMBER_NAME)) { - final String shortcut = getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION); + final String shortcut = getActionShortcut(IdeActions.ACTION_CODE_COMPLETION); if (shortcut != null) { - return "Pressing " + shortcut + " without a class qualifier would show all accessible static methods"; + return "Pressing " + shortcut + " twice without a class qualifier would show all accessible static methods"; } } } @@ -488,15 +491,6 @@ public class JavaCompletionContributor extends CompletionContributor { } } - if (parameters.getCompletionType() != CompletionType.CLASS_NAME && shouldSuggestClassNameCompletion(parameters.getPosition())) { - if (CompletionUtil.shouldShowFeature(parameters, CodeCompletionFeatures.EDITING_COMPLETION_CLASSNAME)) { - final String shortcut = getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION); - if (shortcut != null) { - return CompletionBundle.message("completion.class.name.hint", shortcut); - } - } - } - if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 1) { final PsiType[] psiTypes = ExpectedTypesGetter.getExpectedTypes(parameters.getPosition(), true); if (psiTypes.length > 0) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionFeatures.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionFeatures.java index c775281e16ed..ac5cfe25fe3a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionFeatures.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionFeatures.java @@ -27,5 +27,4 @@ public interface JavaCompletionFeatures { @NonNls String SECOND_SMART_COMPLETION_ARRAY_MEMBER = "editing.completion.second.smarttype.array.member"; @NonNls String GLOBAL_MEMBER_NAME = "editing.completion.global.member.name"; @NonNls String AFTER_NEW = "editing.completion.smarttype.afternew"; - @NonNls String AFTER_NEW_ANONYMOUS = "editing.completion.smarttype.afternew"; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java index 04aca7f2c49c..968199205071 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberNameCompletionContributor.java @@ -1,5 +1,6 @@ package com.intellij.codeInsight.completion; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.VariableLookupItem; import com.intellij.psi.*; @@ -15,7 +16,7 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib @Override public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) { - if (parameters.getCompletionType() != CompletionType.CLASS_NAME) { + if (!parameters.isExtendedCompletion()) { return; } @@ -46,9 +47,9 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib shouldImport |= originalPosition != null && PsiTreeUtil.isAncestor(containingClass, originalPosition, false); if (member instanceof PsiMethod) { - return new JavaMethodCallElement((PsiMethod)member, shouldImport, false); + return AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(new JavaMethodCallElement((PsiMethod)member, shouldImport, false)); } - return new VariableLookupItem((PsiField)member, shouldImport); + return AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(new VariableLookupItem((PsiField)member, shouldImport)); } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 4515b75d36a6..00021004bb24 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -34,7 +34,7 @@ import com.intellij.psi.*; import com.intellij.psi.controlFlow.ControlFlowUtil; import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef; import com.intellij.psi.impl.source.jsp.jspJava.JspClass; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; @@ -106,7 +106,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } private void registerReferencesFromInjectedFragments(final PsiElement element) { - InjectedLanguageFacadeImpl.enumerate(element, myFile, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() { + InjectedLanguageUtil.enumerate(element, myFile, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List places) { injectedPsi.accept(REGISTER_REFERENCES_VISITOR); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java index 7cdd4e046204..f5be3020e01d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java @@ -20,7 +20,6 @@ import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateEditingAdapter; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; @@ -33,7 +32,6 @@ import org.jetbrains.annotations.NotNull; * @author Mike */ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { - private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.CreateFieldFromUsageFix"); public CreateFieldFromUsageFix(PsiReferenceExpression referenceElement) { super(referenceElement); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index 456812925a0d..02113f04207e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -623,6 +623,7 @@ public class CreateFromUsageUtils { getExpectedInformation(expression, typesList, expectedMethodNames, expectedFieldNames); + if (typesList.size() == 1 && (!expectedFieldNames.isEmpty() || !expectedMethodNames.isEmpty())) { ExpectedTypeInfo[] infos = typesList.get(0); if (infos.length == 1 && infos[0].getKind() == ExpectedTypeInfo.TYPE_OR_SUBTYPE && diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseColorIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseColorIntentionAction.java new file mode 100644 index 000000000000..adde45b86af6 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseColorIntentionAction.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2012 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.codeInsight.intention.impl; + +import com.intellij.codeInsight.intention.HighPriorityAction; +import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.intellij.patterns.PlatformPatterns.psiElement; + +/** + * @author Danila Ponomarenko + */ +public abstract class BaseColorIntentionAction extends PsiElementBaseIntentionAction implements HighPriorityAction { + protected static final String JAVA_AWT_COLOR = "java.awt.Color"; + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + if (!psiElement().inside(psiElement(PsiNewExpression.class)).accepts(element)) { + return false; + } + + final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false); + if (expression == null) { + return false; + } + + return isJavaAwtColor(expression.getClassOrAnonymousClassReference()) && isValueArguments(expression.getArgumentList()); + } + + private static boolean isJavaAwtColor(@Nullable PsiJavaCodeReferenceElement ref) { + if (ref == null) { + return false; + } + + final PsiReference reference = ref.getReference(); + if (reference == null) { + return false; + } + + final PsiElement psiElement = reference.resolve(); + if (psiElement instanceof PsiClass && JAVA_AWT_COLOR.equals(((PsiClass)psiElement).getQualifiedName())) { + return true; + } + + return false; + } + + private static boolean isValueArguments(@Nullable PsiExpressionList arguments) { + if (arguments == null) { + return false; + } + + for (PsiExpression argument : arguments.getExpressions()) { + if (argument instanceof PsiReferenceExpression) { + return false; + } + } + + return true; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BreakStringOnLineBreaksIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BreakStringOnLineBreaksIntentionAction.java new file mode 100644 index 000000000000..ea3398efff57 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BreakStringOnLineBreaksIntentionAction.java @@ -0,0 +1,110 @@ +/* + * Copyright 2000-2012 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.codeInsight.intention.impl; + +import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +/** + * @author Danila Ponomarenko + */ +public class BreakStringOnLineBreaksIntentionAction extends PsiElementBaseIntentionAction { + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + if (!(element instanceof PsiJavaToken)) { + return false; + } + + final PsiJavaToken token = (PsiJavaToken)element; + + if (token.getTokenType() != JavaTokenType.STRING_LITERAL) { + return false; + } + + final String text = token.getText(); + if (text == null) { + return false; + } + + final int indexOfSlashN = text.indexOf("\\n"); + final int indexOfSlashNSlashR = text.indexOf("\\n\\r"); + + if (indexOfSlashN == -1 || Comparing.equal(text.substring(indexOfSlashN, text.length()), "\\n\"")){ + return false; + } + + if (indexOfSlashNSlashR != -1 && Comparing.equal(text.substring(indexOfSlashNSlashR, text.length()), "\\n\\r\"")){ + return false; + } + + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { + if (!(element instanceof PsiJavaToken)) { + return; + } + + final PsiJavaToken token = (PsiJavaToken)element; + + if (token.getTokenType() != JavaTokenType.STRING_LITERAL) { + return; + } + + + final String text = token.getText(); + if (text == null) { + return; + } + + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + token.replace(factory.createExpressionFromText(breakOnLineBreaks(text), element)); + } + + + @NotNull + private static String breakOnLineBreaks(@NotNull String string) { + final String result = StringUtil.replace( + string, + new String[]{"\\n\\r", "\\n"}, + new String[]{"\\n\\r\" + \n\"", "\\n\" + \n\""} + ); + + final String redundantSuffix = " + \n\"\""; + + return result.endsWith(redundantSuffix) ? result.substring(0, result.length() - redundantSuffix.length()) : result; + } + + @NotNull + @Override + public String getText() { + return CodeInsightBundle.message("intention.break.string.on.line.breaks.text"); + } + + @NotNull + @Override + public String getFamilyName() { + return getText(); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java index 6434247509b4..3f1c3b6f6f81 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ColorChooserIntentionAction.java @@ -46,9 +46,7 @@ import static com.intellij.patterns.PlatformPatterns.psiElement; * @author spleaner * @author Konstantin Bulenkov */ -public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction { - private static final String JAVA_AWT_COLOR = "java.awt.Color"; - +public class ColorChooserIntentionAction extends BaseColorIntentionAction { private static final PsiMethodPattern DECODE_METHOD = PsiJavaPatterns.psiMethod() .definedInClass(JAVA_AWT_COLOR) .withName("decode"); @@ -64,20 +62,7 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction { @Override public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) { - // new Color(...) - if (psiElement().inside(psiElement(PsiNewExpression.class)).accepts(element)) { - final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false); - if (expression != null) { - final PsiJavaCodeReferenceElement ref = PsiTreeUtil.getChildOfType(expression, PsiJavaCodeReferenceElement.class); - if (isJavaAwtColor(ref)) return true; - } - } - // Color.decode("...") - if (isInsideDecodeOrGetColorMethod(element)) { - return true; - } - - return false; + return super.isAvailable(project, editor, element) || isInsideDecodeOrGetColorMethod(element); } public static boolean isInsideDecodeOrGetColorMethod(PsiElement element) { @@ -85,24 +70,10 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction { element = element.getParent(); } - return PsiJavaPatterns.psiExpression().methodCallParameter(0, DECODE_METHOD).accepts(element) - || + return PsiJavaPatterns.psiExpression().methodCallParameter(0, DECODE_METHOD).accepts(element) || PsiJavaPatterns.psiExpression().methodCallParameter(0, GET_COLOR_METHOD).accepts(element); } - private static boolean isJavaAwtColor(final PsiJavaCodeReferenceElement ref) { - if (ref != null) { - final PsiReference reference = ref.getReference(); - if (reference != null) { - final PsiElement psiElement = reference.resolve(); - if (psiElement instanceof PsiClass && JAVA_AWT_COLOR.equals(((PsiClass)psiElement).getQualifiedName())) { - return true; - } - } - } - return false; - } - @Override @NotNull public String getFamilyName() { @@ -116,7 +87,8 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction { final JComponent editorComponent = editor.getComponent(); if (isInsideDecodeOrGetColorMethod(element)) { invokeForMethodParam(editorComponent, element); - } else { + } + else { invokeForConstructor(editorComponent, element); } } @@ -139,9 +111,9 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction { if (color == null) return; final int rgb = color.getRGB() - ((255 & 0xFF) << 24); if (color != null && rgb != oldColor.getRGB()) { - final String newText = radix == 16 ? hexPrefix + String.format("%6s" ,Integer.toHexString(rgb)).replace(' ', '0') - : radix == 8 ? "0" + Integer.toOctalString(rgb) - : Integer.toString(rgb); + final String newText = radix == 16 ? hexPrefix + String.format("%6s", Integer.toHexString(rgb)).replace(' ', '0') + : radix == 8 ? "0" + Integer.toOctalString(rgb) + : Integer.toString(rgb); final PsiManager manager = literal.getManager(); final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final PsiExpression newLiteral = factory.createExpressionFromText("\"" + newText + "\"", literal); @@ -221,12 +193,12 @@ public class ColorChooserIntentionAction extends PsiElementBaseIntentionAction { final PsiManager manager = expression.getManager(); final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final PsiExpression newCall = factory.createExpressionFromText( - "new " + JAVA_AWT_COLOR +"(" - + color.getRed() + ", " - + color.getGreen() + ", " - + color.getBlue() - + (color.getAlpha() < 255 ? ", " + color.getAlpha() : "") - +")", expression); + "new " + JAVA_AWT_COLOR + "(" + + color.getRed() + ", " + + color.getGreen() + ", " + + color.getBlue() + + (color.getAlpha() < 255 ? ", " + color.getAlpha() : "") + + ")", expression); final PsiElement insertedElement = expression.replace(newCall); final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); codeStyleManager.reformat(insertedElement); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java index cc2295d1c616..b3b533597c71 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.intention.impl; +import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; @@ -38,7 +39,6 @@ public class ConvertAbsolutePathToRelativeIntentionAction extends BaseIntentionA @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset()); final FileReference fileReference = reference == null ? null : findFileReference(reference); @@ -81,6 +81,8 @@ public class ConvertAbsolutePathToRelativeIntentionAction extends BaseIntentionA @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; + final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset()); final FileReference fileReference = reference == null ? null : findFileReference(reference); if (fileReference != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertColorRepresentationIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertColorRepresentationIntentionAction.java new file mode 100644 index 000000000000..c3944ba6158b --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertColorRepresentationIntentionAction.java @@ -0,0 +1,226 @@ +/* + * Copyright 2000-2012 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.codeInsight.intention.impl; + +import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.codeInsight.CodeInsightUtilBase; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.impl.JavaConstantExpressionEvaluator; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Danila Ponomarenko + */ +public class ConvertColorRepresentationIntentionAction extends BaseColorIntentionAction { + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + if (!super.isAvailable(project, editor, element)) { + return false; + } + + final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false); + if (expression == null) { + return false; + } + + final PsiExpressionList arguments = expression.getArgumentList(); + if (arguments == null) { + return false; + } + + final PsiMethod constructor = expression.resolveConstructor(); + if (constructor == null) { + return false; + } + + final PsiExpressionList newArguments = createNewArguments(JavaPsiFacade.getElementFactory(project), constructor.getParameterList().getParameters(), arguments.getExpressions()); + + if (newArguments == null) { + return false; + } + + setText(CodeInsightBundle.message("intention.convert.color.representation.text", newArguments.getText())); + + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { + if (!CodeInsightUtilBase.preparePsiElementForWrite(element)) return; + + final PsiNewExpression expression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class, false); + if (expression == null) { + return; + } + + final PsiExpressionList arguments = expression.getArgumentList(); + if (arguments == null) { + return; + } + + final PsiMethod constructor = expression.resolveConstructor(); + if (constructor == null) { + return; + } + + final PsiExpressionList newArguments = createNewArguments( + JavaPsiFacade.getElementFactory(project), + constructor.getParameterList().getParameters(), + arguments.getExpressions() + ); + + if (newArguments == null) { + return; + } + + arguments.replace(newArguments); + } + + @Nullable + private static PsiExpressionList createNewArguments(@NotNull PsiElementFactory factory, + @NotNull PsiParameter[] parameters, + @NotNull PsiExpression[] arguments) { + final String[] newValues = createArguments(parameters, arguments); + if (newValues == null) { + return null; + } + + final PsiExpressionList result = ((PsiNewExpression)factory.createExpressionFromText("new Object()", parameters[0])).getArgumentList(); + if (result == null) { + return null; + } + for (String value : newValues) { + result.add(factory.createExpressionFromText(value, parameters[0])); + } + return result; + } + + @Nullable + private static String[] createArguments(@NotNull PsiParameter[] parameters, + @NotNull PsiExpression[] arguments) { + if (parameters.length != arguments.length) { + return null; + } + + switch (parameters.length) { + default: + return null; + case 1: + return createArguments(arguments[0]); + case 2: + return createArguments(arguments[0], arguments[1]); + case 3: + return createArguments(arguments[0], arguments[1], arguments[2]); + case 4: + return createArguments(arguments[0], arguments[1], arguments[2], arguments[3]); + } + } + + @Nullable + private static String[] createArguments(@NotNull PsiExpression rgbExpression) { + return createArguments(rgbExpression, 3); + } + + @Nullable + private static String[] createArguments(@NotNull PsiExpression rgbExpression, + @NotNull PsiExpression hasAlphaExpression) { + final Boolean hasAlpha = computeBoolean(hasAlphaExpression); + if (hasAlpha == null) { + return null; + } + return hasAlpha ? createArguments(rgbExpression, 4) : createArguments(rgbExpression); + } + + @Nullable + private static String[] createArguments(@NotNull PsiExpression rExpression, + @NotNull PsiExpression gExpression, + @NotNull PsiExpression bExpression) { + final Integer value = createInt(computeInteger(rExpression), computeInteger(gExpression), computeInteger(bExpression)); + return value != null ? new String[]{"0x" + Integer.toHexString(value)} : null; + } + + @Nullable + private static String[] createArguments(@NotNull PsiExpression rExpression, + @NotNull PsiExpression gExpression, + @NotNull PsiExpression bExpression, + @NotNull PsiExpression aExpression) { + final Integer value = createInt(computeInteger(rExpression), computeInteger(gExpression), computeInteger(bExpression), computeInteger(aExpression)); + if (value == null) { + return null; + } + + return new String[]{ + "0x" + Integer.toHexString(value), + "true", + }; + } + + @Nullable + private static String[] createArguments(@NotNull PsiExpression rgbExpression, + int parts) { + final Integer rgb = computeInteger(rgbExpression); + if (rgb == null) { + return null; + } + + final String[] result = new String[parts]; + for (int i = 0; i < result.length; i++) { + result[result.length - i - 1] = String.valueOf(rgb >> (i * Byte.SIZE) & 0xFF); + } + return result; + } + + @Nullable + private static Integer createInt(Integer... ints) { + int result = 0; + for (Integer i : ints) { + if (i == null) { + return null; + } + result = result << Byte.SIZE | (i & 0xFF); + } + return result; + } + + @Nullable + public static Integer computeInteger(@NotNull PsiExpression expr) { + final Object result = compute(expr); + return result instanceof Integer ? (Integer)result : null; + } + + @Nullable + public static Boolean computeBoolean(@NotNull PsiExpression expr) { + final Object result = compute(expr); + return result instanceof Boolean ? (Boolean)result : null; + } + + @Nullable + private static Object compute(@NotNull PsiExpression expr) { + return JavaConstantExpressionEvaluator.computeConstantExpression(expr, true); + } + + @NotNull + @Override + public String getFamilyName() { + return CodeInsightBundle.message("intention.convert.color.representation.family"); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/TypeExpression.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/TypeExpression.java index b0247a387e84..804ba2452b45 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/TypeExpression.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/TypeExpression.java @@ -28,10 +28,9 @@ import com.intellij.psi.*; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; public class TypeExpression extends Expression { - private final Set myItems; + private final LinkedHashSet myItems; public TypeExpression(final Project project, PsiType[] types) { final SmartTypePointerManager manager = SmartTypePointerManager.getInstance(project); diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java index 9dfa90f5b4f2..1c0e61dd384a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.lookup; import com.intellij.codeInsight.completion.*; +import com.intellij.ide.highlighter.XmlLikeFileType; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.util.ClassConditionKey; @@ -79,7 +80,11 @@ public class PsiTypeLookupItem extends LookupItem { PsiElement position = context.getFile().findElementAt(context.getStartOffset()); assert position != null; int genericsStart = context.getTailOffset(); - context.getDocument().insertString(genericsStart, calcGenerics(position, context)); + String generics = calcGenerics(position, context); + if (context.getFile().getFileType() instanceof XmlLikeFileType) { + generics = StringUtil.escapeXml(generics); + } + context.getDocument().insertString(genericsStart, generics); JavaCompletionUtil.shortenReference(context.getFile(), genericsStart - 1); int tail = context.getTailOffset(); diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java index c6c6095a2a1b..2c831bbdc8dd 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java @@ -34,6 +34,7 @@ import com.intellij.codeInspection.*; import com.intellij.codeInspection.dataFlow.instructions.*; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; import com.intellij.ide.DataManager; +import com.intellij.lang.ASTFactory; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -41,6 +42,8 @@ import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Pair; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.impl.source.codeStyle.CodeFormatterFacade; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; @@ -230,8 +233,11 @@ public class DataFlowInspection extends BaseLocalInspectionTool { else if (psiAnchor != null && !reportedAnchors.contains(psiAnchor) && !isCompileConstantInIfCondition(psiAnchor)) { boolean evaluatesToTrue = trueSet.contains(instruction); if (onTheLeftSideOfConditionalAssignemnt(psiAnchor)) { - holder.registerProblem(psiAnchor, InspectionsBundle.message("dataflow.message.pointless.assignment.expression", - Boolean.toString(evaluatesToTrue))); + holder.registerProblem( + psiAnchor, + InspectionsBundle.message("dataflow.message.pointless.assignment.expression", Boolean.toString(evaluatesToTrue)), + createSimplifyToAssignmentFix() + ); } else { boolean report = !(psiAnchor.getParent() instanceof PsiAssertStatement) || !DONT_REPORT_TRUE_ASSERT_STATEMENTS || !evaluatesToTrue; @@ -370,6 +376,40 @@ public class DataFlowInspection extends BaseLocalInspectionTool { }; } + @NotNull + private static LocalQuickFix createSimplifyToAssignmentFix() { + return new LocalQuickFix() { + @NotNull + @Override + public String getName() { + return InspectionsBundle.message("inspection.data.flow.simplify.to.assignment.quickfix.name"); + } + + @NotNull + @Override + public String getFamilyName() { + return InspectionsBundle.message("inspection.data.flow.simplify.boolean.expression.quickfix"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement psiElement = descriptor.getPsiElement(); + if (psiElement == null) return; + + final PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(psiElement, PsiAssignmentExpression.class); + if (assignmentExpression == null) { + return; + } + + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + final String lExpressionText = assignmentExpression.getLExpression().getText(); + final PsiExpression rExpression = assignmentExpression.getRExpression(); + final String rExpressionText = rExpression != null ? rExpression.getText() : ""; + assignmentExpression.replace(factory.createExpressionFromText(lExpressionText + " = " + rExpressionText, psiElement)); + } + }; + } + private static SimplifyBooleanExpressionFix createIntention(PsiElement element, boolean value) { if (!(element instanceof PsiExpression)) return null; final PsiExpression expression = (PsiExpression)element; diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java index 935ca9d9dcbe..71c2da6cf150 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java @@ -27,14 +27,15 @@ package com.intellij.codeInspection.dataFlow; import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.codeInspection.dataFlow.value.DfaTypeValue; import com.intellij.codeInspection.dataFlow.value.DfaValue; -import com.intellij.psi.PsiPrimitiveType; -import com.intellij.psi.PsiVariable; +import com.intellij.codeInspection.nullable.NullableStuffInspection; +import com.intellij.psi.*; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Set; public class DfaVariableState implements Cloneable { @@ -48,8 +49,36 @@ public class DfaVariableState implements Cloneable { myVar = var; myInstanceofValues = new HashSet(); myNotInstanceofValues = new HashSet(); - myNullable = var != null && NullableNotNullManager.isNullable(var); - myVariableIsDeclaredNotNull = var != null && NullableNotNullManager.isNotNull(var); + myNullable = var != null && (NullableNotNullManager.isNullable(var) || isNullableInitialized(var, true)); + myVariableIsDeclaredNotNull = var != null && (NullableNotNullManager.isNotNull(var) || isNullableInitialized(var, false)); + } + + private static boolean isNullableInitialized(PsiVariable var, boolean nullable) { + if (!var.hasModifierProperty(PsiModifier.FINAL) || !(var instanceof PsiField)) { + return false; + } + + List initializers = NullableStuffInspection.findAllConstructorInitializers((PsiField)var); + if (initializers.isEmpty()) { + return false; + } + + for (PsiExpression expression : initializers) { + if (!(expression instanceof PsiReferenceExpression)) { + return false; + } + PsiElement target = ((PsiReferenceExpression)expression).resolve(); + if (!(target instanceof PsiParameter)) { + return false; + } + if (nullable && NullableNotNullManager.isNullable((PsiParameter)target)) { + return true; + } + if (!nullable && !NullableNotNullManager.isNotNull((PsiParameter)target)) { + return false; + } + } + return !nullable; } protected DfaVariableState(final DfaVariableState toClone) { diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java index b58d9a6a8ab7..3162b39fefd8 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java @@ -42,8 +42,8 @@ import com.intellij.psi.util.*; import com.intellij.refactoring.psi.PropertyUtils; import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; -import com.intellij.util.Query; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -51,6 +51,9 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; +import static com.intellij.util.containers.ContainerUtil.addIfNotNull; +import static com.intellij.util.containers.ContainerUtilRt.createEmptyCOWList; + public class NullableStuffInspection extends BaseLocalInspectionTool { // deprecated fields remain to minimize changes to users inspection profiles (which are often located in version control). @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL = true; @@ -173,40 +176,13 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove))); } } - if (containingClass == null) { - return; - } - final PsiMethod[] constructors = containingClass.getConstructors(); - final Query search = ReferencesSearch.search(field, new LocalSearchScope(constructors), false); - search.forEach(new Processor() { - @Override - public boolean process(PsiReference reference) { - final PsiElement element = reference.getElement(); - if (!(element instanceof PsiReferenceExpression)) { - return true; - } - PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element; - final PsiAssignmentExpression assignmentExpression = getAssignmentExpressionIfOnAssignmentLefthand(referenceExpression); - final PsiMethod method = PsiTreeUtil.getParentOfType(assignmentExpression, PsiMethod.class); - if (method == null || !method.isConstructor()) { - return true; - } - if (assignmentExpression == null) { - return true; - } - final PsiExpression rhs = assignmentExpression.getRExpression(); - if (!(rhs instanceof PsiReferenceExpression)) { - return true; - } - PsiReferenceExpression expression = (PsiReferenceExpression)rhs; - final PsiElement target = expression.resolve(); - if (!(target instanceof PsiParameter)) { - return true; - } - final PsiParameter parameter = (PsiParameter)target; - if (!method.equals(parameter.getDeclarationScope())) { - return true; - } + } + + for (PsiExpression rhs : findAllConstructorInitializers(field)) { + if (rhs instanceof PsiReferenceExpression) { + PsiElement target = ((PsiReferenceExpression)rhs).resolve(); + if (target instanceof PsiParameter) { + PsiParameter parameter = (PsiParameter)target; if (REPORT_NOT_ANNOTATED_GETTER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations()) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier(); assert nameIdentifier2 != null : parameter; @@ -214,7 +190,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { .message("inspection.nullable.problems.annotated.field.constructor.parameter.not.annotated", StringUtil.getShortName(anno)), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove))); - return true; + continue; } if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false)) { final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier(); @@ -234,9 +210,9 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AddAnnotationFix(anno, parameter, ArrayUtil.toStringArray(annoToRemove))); } - return true; + } - }); + } } } } @@ -246,18 +222,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { LOG.assertTrue(parameter.isPhysical(), setter.getText()); } - public PsiAssignmentExpression getAssignmentExpressionIfOnAssignmentLefthand(PsiExpression expression) { - PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class); - if (!(parent instanceof PsiAssignmentExpression)) { - return null; - } - final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent; - if (!PsiTreeUtil.isAncestor(assignmentExpression.getLExpression(), expression, false)) { - return null; - } - return assignmentExpression; - } - @Override public void visitParameter(PsiParameter parameter) { if (!PsiUtil.isLanguageLevel5OrHigher(parameter)) return; check(parameter, holder, parameter.getType()); @@ -519,4 +483,42 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD = myReportNullsPassedToNonAnnotatedParameter.isSelected(); } } + + public static List findAllConstructorInitializers(PsiField field) { + final List result = createEmptyCOWList(); + addIfNotNull(result, field.getInitializer()); + + PsiClass containingClass = field.getContainingClass(); + if (containingClass != null) { + LocalSearchScope scope = new LocalSearchScope(containingClass.getConstructors()); + ReferencesSearch.search(field, scope, false).forEach(new Processor() { + @Override + public boolean process(PsiReference reference) { + final PsiElement element = reference.getElement(); + if (element instanceof PsiReferenceExpression) { + final PsiAssignmentExpression assignment = getAssignmentExpressionIfOnAssignmentLhs(element); + final PsiMethod method = PsiTreeUtil.getParentOfType(assignment, PsiMethod.class); + if (method != null && method.isConstructor() && assignment != null) { + addIfNotNull(result, assignment.getRExpression()); + } + } + return true; + } + }); + } + return result; + } + + @Nullable + private static PsiAssignmentExpression getAssignmentExpressionIfOnAssignmentLhs(PsiElement expression) { + PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class); + if (!(parent instanceof PsiAssignmentExpression)) { + return null; + } + final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent; + if (!PsiTreeUtil.isAncestor(assignmentExpression.getLExpression(), expression, false)) { + return null; + } + return assignmentExpression; + } } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index dd93897539f0..232247dd5277 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -34,7 +34,7 @@ import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.codeStyle.ShiftIndentInsideHelper; import com.intellij.psi.impl.source.tree.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.impl.source.tree.java.ClassElement; import com.intellij.psi.jsp.JspElementType; import com.intellij.psi.tree.IElementType; @@ -172,7 +172,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (isStatement(child, child.getTreeParent())) { return new CodeBlockBlock(child, wrap, alignment, actualIndent, settings); } - if (child instanceof PsiComment && child instanceof PsiLanguageInjectionHost && InjectedLanguageFacadeImpl + if (child instanceof PsiComment && child instanceof PsiLanguageInjectionHost && InjectedLanguageUtil .hasInjections((PsiLanguageInjectionHost)child)) { return new CommentWithInjectionBlock(child, wrap, alignment, indent, settings); } diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java b/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java index 23c07d65a139..8b40b441006b 100644 --- a/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java +++ b/java/java-impl/src/com/intellij/usages/impl/rules/ClassGroupingRule.java @@ -25,7 +25,7 @@ import com.intellij.openapi.util.Iconable; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.jsp.JspFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.usageView.UsageInfo; @@ -48,7 +48,7 @@ public class ClassGroupingRule implements UsageGroupingRule { } final PsiElement psiElement = ((PsiElementUsage)usage).getElement(); final PsiFile containingFile = psiElement.getContainingFile(); - PsiFile topLevelFile = InjectedLanguageFacadeImpl.getTopLevelFile(containingFile); + PsiFile topLevelFile = InjectedLanguageUtil.getTopLevelFile(containingFile); if (!(topLevelFile instanceof PsiJavaFile) || topLevelFile instanceof JspFile) { return null; diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java b/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java index c82180d92721..ec3e39f92939 100644 --- a/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java +++ b/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java @@ -28,7 +28,7 @@ import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Segment; import com.intellij.openapi.vcs.FileStatus; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiTreeUtil; @@ -51,7 +51,7 @@ public class MethodGroupingRule implements UsageGroupingRule { if (!(usage instanceof PsiElementUsage)) return null; PsiElement psiElement = ((PsiElementUsage)usage).getElement(); PsiFile containingFile = psiElement.getContainingFile(); - PsiFile topLevelFile = InjectedLanguageFacadeImpl.getTopLevelFile(containingFile); + PsiFile topLevelFile = InjectedLanguageUtil.getTopLevelFile(containingFile); if (topLevelFile instanceof PsiJavaFile) { PsiElement containingMethod = topLevelFile == containingFile ? psiElement : InjectedLanguageManager .getInstance(containingFile.getProject()).getInjectionHost(containingFile); diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java index 1eb3ae340a0e..65b09c3f42d4 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java @@ -24,31 +24,31 @@ import org.jetbrains.annotations.Nullable; import java.util.Map; public class PsiTypesUtil { - @NonNls private static final Map ourUnboxedTypes = new THashMap(); - @NonNls private static final Map ourBoxedTypes = new THashMap(); + @NonNls private static final Map ourUnboxedTypes = new THashMap() {{ + put(CommonClassNames.JAVA_LANG_BOOLEAN, "boolean"); + put(CommonClassNames.JAVA_LANG_BYTE, "byte"); + put(CommonClassNames.JAVA_LANG_SHORT, "short"); + put(CommonClassNames.JAVA_LANG_INTEGER, "int"); + put(CommonClassNames.JAVA_LANG_LONG, "long"); + put(CommonClassNames.JAVA_LANG_FLOAT, "float"); + put(CommonClassNames.JAVA_LANG_DOUBLE, "double"); + put(CommonClassNames.JAVA_LANG_CHARACTER, "char"); + }}; - static { - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_BOOLEAN, "boolean"); - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_BYTE, "byte"); - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_SHORT, "short"); - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_INTEGER, "int"); - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_LONG, "long"); - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_FLOAT, "float"); - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_DOUBLE, "double"); - ourUnboxedTypes.put(CommonClassNames.JAVA_LANG_CHARACTER, "char"); + @NonNls private static final Map ourBoxedTypes = new THashMap() {{ + put("boolean", CommonClassNames.JAVA_LANG_BOOLEAN); + put("byte", CommonClassNames.JAVA_LANG_BYTE); + put("short", CommonClassNames.JAVA_LANG_SHORT); + put("int", CommonClassNames.JAVA_LANG_INTEGER); + put("long", CommonClassNames.JAVA_LANG_LONG); + put("float", CommonClassNames.JAVA_LANG_FLOAT); + put("double", CommonClassNames.JAVA_LANG_DOUBLE); + put("char", CommonClassNames.JAVA_LANG_CHARACTER); + }}; - ourBoxedTypes.put("boolean", CommonClassNames.JAVA_LANG_BOOLEAN); - ourBoxedTypes.put("byte", CommonClassNames.JAVA_LANG_BYTE); - ourBoxedTypes.put("short", CommonClassNames.JAVA_LANG_SHORT); - ourBoxedTypes.put("int", CommonClassNames.JAVA_LANG_INTEGER); - ourBoxedTypes.put("long", CommonClassNames.JAVA_LANG_LONG); - ourBoxedTypes.put("float", CommonClassNames.JAVA_LANG_FLOAT); - ourBoxedTypes.put("double", CommonClassNames.JAVA_LANG_DOUBLE); - ourBoxedTypes.put("char", CommonClassNames.JAVA_LANG_CHARACTER); + private PsiTypesUtil() { } - private PsiTypesUtil() { } - public static String getDefaultValueOfType(PsiType type) { if (type instanceof PsiArrayType) { int count = type.getArrayDimensions() - 1; @@ -86,6 +86,7 @@ public class PsiTypesUtil { /** * Returns the unboxed type name or parameter. + * * @param type boxed java type name * @return unboxed type name if available; same value otherwise */ @@ -93,11 +94,12 @@ public class PsiTypesUtil { public static String unboxIfPossible(final String type) { if (type == null) return null; final String s = ourUnboxedTypes.get(type); - return s == null? type : s; + return s == null ? type : s; } /** * Returns the boxed type name or parameter. + * * @param type primitive java type name * @return boxed type name if available; same value otherwise */ @@ -110,7 +112,7 @@ public class PsiTypesUtil { @Nullable public static PsiClass getPsiClass(final PsiType psiType) { - return psiType instanceof PsiClassType? ((PsiClassType)psiType).resolve() : null; + return psiType instanceof PsiClassType ? ((PsiClassType)psiType).resolve() : null; } public static PsiClassType getClassType(@NotNull PsiClass psiClass) { diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreselectMostRelevantInTheMiddleAlpha.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreselectMostRelevantInTheMiddleAlpha.java index e7bd758c7104..34da2cfa1e58 100644 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/PreselectMostRelevantInTheMiddleAlpha.java +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreselectMostRelevantInTheMiddleAlpha.java @@ -1,17 +1,17 @@ class Foo { - int ELEMENT_A = 1; - int ELEMENT_B = 1; - int ELEMENT_C = 1; - int ELEMENT_D = 1; - int ELEMENT_E = 1; - int ELEMENT_F = 1; - int ELEMENT_G = 1; - int ELEMENT_H = 1; - int ELEMENT_I = 1; + int ELXEMENT_A = 1; + int ELXEMENT_B = 1; + int ELXEMENT_C = 1; + int ELXEMENT_D = 1; + int ELXEMENT_E = 1; + int ELXEMENT_F = 1; + int ELXEMENT_G = 1; + int ELXEMENT_H = 1; + int ELXEMENT_I = 1; { - El + Elx } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/afterAll.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/afterAll.java new file mode 100644 index 000000000000..c921867b407c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/afterAll.java @@ -0,0 +1,7 @@ +// "Break string on '\n'" "true" + +class A { + String s = "Hello,\n\r" + + "world\n" + + "!\n"; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeAll.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeAll.java new file mode 100644 index 000000000000..a87961b68b9e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeAll.java @@ -0,0 +1,5 @@ +// "Break string on '\n'" "true" + +class A { + String s = "Hello,\n\rworld\n!\n"; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeLastSlashN.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeLastSlashN.java new file mode 100644 index 000000000000..0de2f83afa6a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeLastSlashN.java @@ -0,0 +1,5 @@ +// "Break string on '\n'" "false" + +class A { + String s = "Hello!\n"; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeLastSlashNSlashR.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeLastSlashNSlashR.java new file mode 100644 index 000000000000..c18a560abff9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks/beforeLastSlashNSlashR.java @@ -0,0 +1,5 @@ +// "Break string on '\n'" "false" + +class A { + String s = "Hello!\n\r"; +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/after2Bytes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/after2Bytes.java new file mode 100644 index 000000000000..a2412d27557a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/after2Bytes.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(0x10101)'" "true" + +package java.awt; + +class A { + private Color color = new Color(0x10101); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterHex2Rgb.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterHex2Rgb.java new file mode 100644 index 000000000000..18f771434d33 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterHex2Rgb.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(37, 100, 120)'" "true" + +package java.awt; + +public class A { + private Color color = new Color(37, 100, 120); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterHexA2Rgba.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterHexA2Rgba.java new file mode 100644 index 000000000000..70171b80b283 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterHexA2Rgba.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(37, 100, 120, 140)'" "true" + +package java.awt; + +class A { + private Color color = new Color(37, 100, 120, 140); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterRgb2Hex.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterRgb2Hex.java new file mode 100644 index 000000000000..c46980af5d4b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterRgb2Hex.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(0x256478)'" "true" + +package java.awt; + +class A { + private Color color = new Color(0x256478); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterRgba2Hex.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterRgba2Hex.java new file mode 100644 index 000000000000..488f9401c649 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/afterRgba2Hex.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(0x2564788c,true)'" "true" + +package java.awt; + +class A { + private Color color = new Color(0x2564788c, true); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/before2Bytes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/before2Bytes.java new file mode 100644 index 000000000000..8396cba9cc2e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/before2Bytes.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(0x10101)'" "true" + +package java.awt; + +class A { + private Color color = new Color(257, 257, 257); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeHex2Rgb.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeHex2Rgb.java new file mode 100644 index 000000000000..666394ed293b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeHex2Rgb.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(37, 100, 120)'" "true" + +package java.awt; + +public class A { + private Color color = new Color(0x256478); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeHexA2Rgba.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeHexA2Rgba.java new file mode 100644 index 000000000000..39762cdfd810 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeHexA2Rgba.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(37, 100, 120, 140)'" "true" + +package java.awt; + +class A { + private Color color = new Color(0x2564788c, true); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeRgb2Hex.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeRgb2Hex.java new file mode 100644 index 000000000000..10f6bc144124 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeRgb2Hex.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(0x256478)'" "true" + +package java.awt; + +class A { + private Color color = new Color(37, 100, 120); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeRgba2Hex.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeRgba2Hex.java new file mode 100644 index 000000000000..cfe125593699 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation/beforeRgba2Hex.java @@ -0,0 +1,21 @@ +// "Convert to 'new Color(0x2564788c,true)'" "true" + +package java.awt; + +class A { + private Color color = new Color(37, 100, 120, 140); +} + +class Color { + Color(int r, int g, int b) { + } + + Color(int r, int g, int b, int a) { + } + + Color(int rgb) { + } + + Color(int rgba, boolean hasAlpha) { + } +} diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FinalFieldsInitializedByAnnotatedParameters.java b/java/java-tests/testData/inspection/dataFlow/fixture/FinalFieldsInitializedByAnnotatedParameters.java new file mode 100644 index 000000000000..db7d0b479d1f --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/FinalFieldsInitializedByAnnotatedParameters.java @@ -0,0 +1,30 @@ +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.Object; + +public class Doo { + private final Object myA; + private final Object myB; + private final Object myC; + + public Doo(@Nullable Object myA, @NotNull Object myB, Object c) { + this.myA = myA; + this.myB = myB; + myC = c; + } + + int bar() { + return myC.hashCode(); + } + + + int foo() { + if (myB != null && + myA.equals(myB)) { + return 2; + } + + return myA.hashCode(); + } +} diff --git a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/expected.xml b/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/expected.xml index 07441b9e8513..e83b29bd9fea 100644 --- a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/expected.xml +++ b/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/expected.xml @@ -62,4 +62,12 @@ Constructor parameter for @NotNull field might be annotated @NotNull itself + + Test.java + 63 + @NotNull/@Nullable problems + Constructor parameter for @NotNull field might be annotated @NotNull itself + + + diff --git a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/src/Test.java b/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/src/Test.java index 39b421f2815a..6fc47b42a232 100644 --- a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/src/Test.java +++ b/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/src/Test.java @@ -55,4 +55,13 @@ class D { D(long l) { myL = l; } +} + +class E { + final @NotNull C c; + + E(C c) { + this.c = c; + } + } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java index c33a5945ab3b..f2ddcd3f4cc6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java @@ -10,6 +10,8 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.ide.ui.UISettings; +import com.intellij.psi.statistics.StatisticsManager; +import com.intellij.psi.statistics.impl.StatisticsManagerImpl; import com.intellij.testFramework.TestDataPath; import org.jetbrains.annotations.NonNls; @@ -25,6 +27,12 @@ public abstract class CompletionSortingTestCase extends LightFixtureCompletionTe myType = type; } + @Override + protected void setUp() throws Exception { + super.setUp(); + ((StatisticsManagerImpl)StatisticsManager.getInstance()).enableStatistics(getTestRootDisposable()); + } + @Override protected void tearDown() throws Exception { LookupManager.getInstance(getProject()).hideActiveLookup(); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionStyleTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionStyleTest.java index 703406feddc6..0ad4a0585a4a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionStyleTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionStyleTest.java @@ -10,8 +10,6 @@ import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -import com.intellij.psi.statistics.StatisticsManager; -import com.intellij.psi.statistics.impl.StatisticsManagerImpl; import com.intellij.testFramework.LightCodeInsightTestCase; import com.intellij.testFramework.TestDataPath; @@ -26,12 +24,6 @@ import com.intellij.testFramework.TestDataPath; public class CompletionStyleTest extends LightCodeInsightTestCase{ private static final String BASE_PATH = "/codeInsight/completion/style"; - @Override - protected void setUp() throws Exception { - super.setUp(); - ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics(); - } - @Override protected LanguageLevel getLanguageLevel() { return LanguageLevel.JDK_1_6; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy index 4a4c202b8c1c..412f5c61c8b6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy @@ -3,7 +3,8 @@ package com.intellij.codeInsight.completion; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.intellij.codeInsight.CodeInsightSettings import com.intellij.util.ArrayUtil -import com.intellij.codeInsight.lookup.LookupElementPresentation; +import com.intellij.codeInsight.lookup.LookupElementPresentation +import com.intellij.codeInsight.lookup.LookupElement; /** * @author peter @@ -65,7 +66,7 @@ public class Foo { } """) myFixture.configureByText "a.java", "class Bar {{ abcf }}" - def element = myFixture.complete(CompletionType.CLASS_NAME)[0] + def element = complete()[0] def presentation = new LookupElementPresentation() element.renderElement(presentation) assert 'Foo.abcfield' == presentation.itemText @@ -73,6 +74,10 @@ public class Foo { assert 'int' == presentation.typeText } + private LookupElement[] complete() { + myFixture.complete(CompletionType.BASIC, 2) + } + public void testQualifiedMethodName() throws Exception { myFixture.addClass(""" package foo; @@ -157,7 +162,7 @@ class Bar {{ abcmethod1() }}""" """) myFixture.configureByText("a.java", "class Bar {{ abcm }}") - myFixture.complete(CompletionType.CLASS_NAME) + complete() assertOrderedEquals myFixture.lookupElementStrings, "abcmethod", "abcmethod1" } @@ -171,7 +176,7 @@ class A { } } """) - def element = myFixture.complete(CompletionType.CLASS_NAME)[0] + def element = complete()[0] def presentation = new LookupElementPresentation() element.renderElement(presentation) assert 'foo' == presentation.itemText @@ -190,7 +195,7 @@ class A { private void doTest(String input, boolean importStatic, String output) { myFixture.configureByText("a.java", input) - def item = assertOneElement(myFixture.complete(CompletionType.CLASS_NAME)) + def item = assertOneElement(complete()) if (importStatic) { item.'as'(StaticallyImportable).shouldBeImported = true } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/LightFixtureCompletionTestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/LightFixtureCompletionTestCase.java index 70c79ed8de79..f634138da2b7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/LightFixtureCompletionTestCase.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/LightFixtureCompletionTestCase.java @@ -5,8 +5,6 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.psi.statistics.StatisticsManager; -import com.intellij.psi.statistics.impl.StatisticsManagerImpl; import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; @@ -17,12 +15,6 @@ import org.jetbrains.annotations.NotNull; public abstract class LightFixtureCompletionTestCase extends LightCodeInsightFixtureTestCase { protected LookupElement[] myItems; - @Override - protected void setUp() throws Exception { - super.setUp(); - ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics(); - } - @NotNull @Override protected LightProjectDescriptor getProjectDescriptor() { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index 3c54a40b6813..05afbdf21c13 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -287,13 +287,13 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { public void testPreselectMostRelevantInTheMiddleAlpha() { UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY = true; - myFixture.addClass("package foo; public class Elaaaaaaaaaaaaaaaaaaaa {}"); + myFixture.addClass("package foo; public class Elxaaaaaaaaaaaaaaaaaaaa {}"); invokeCompletion(getTestName(false) + ".java"); myFixture.completeBasic(); LookupImpl lookup = getLookup(); assertPreferredItems(lookup.getList().getSelectedIndex()); - assertEquals("Elaaaaaaaaaaaaaaaaaaaa", lookup.getItems().get(0).getLookupString()); - assertEquals("ELEMENT_A", lookup.getCurrentItem().getLookupString()); + assertEquals("Elxaaaaaaaaaaaaaaaaaaaa", lookup.getItems().get(0).getLookupString()); + assertEquals("ELXEMENT_A", lookup.getCurrentItem().getLookupString()); } public void testReallyAlphaSorting() { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index cc56df142398..9ae24972daa2 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1110,7 +1110,7 @@ public class ListUtils { public static void bar() {} } """) - doTest() + doTest('\n') } public void testSuggestMembersOfStaticallyImportedClassesUnqualifiedOnly() throws Exception { @@ -1338,7 +1338,7 @@ public class ListUtils { public void testListArrayListCast() { doTest('\n') } public void testInterfaceImplementationNoCast() { doTest() } - public void testStaticallyImportedMethodsBeforeExpression() { doTest() } + public void testStaticallyImportedMethodsBeforeExpression() { doTest('\n') } public void testInnerChainedReturnType() { doTest() } public void testOverwriteGenericsAfterNew() { doTest('\n') } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BreakStringOnLineBreaksTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BreakStringOnLineBreaksTest.java new file mode 100644 index 000000000000..946817269ae4 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BreakStringOnLineBreaksTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2012 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.codeInsight.daemon.quickFix; + +/** + * @author Danila Ponomarenko + */ +public class BreakStringOnLineBreaksTest extends LightQuickFixTestCase { + + public void test() throws Exception { doAllTests(); } + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/breakStringOnLineBreaks"; + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java new file mode 100644 index 000000000000..a13f0781fc32 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2012 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.codeInsight.daemon.quickFix; + +/** + * @author Danila Ponomarenko + */ +public class ConvertColorRepresentationTest extends LightQuickFix15TestCase { + + public void test() throws Exception { doAllTests(); } + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation"; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java index 8202b8371805..cd6c67d36e57 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java @@ -65,5 +65,6 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas public void testStringTernaryAlwaysTrue() throws Throwable { doTest(); } public void testBoxing128() throws Throwable { doTest(); } + public void testFinalFieldsInitializedByAnnotatedParameters() throws Throwable { doTest(); } } diff --git a/java/testFramework/src/com/intellij/codeInsight/completion/CompletionTestCase.java b/java/testFramework/src/com/intellij/codeInsight/completion/CompletionTestCase.java index 8538d84dcd37..1591b3818546 100644 --- a/java/testFramework/src/com/intellij/codeInsight/completion/CompletionTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/completion/CompletionTestCase.java @@ -19,8 +19,6 @@ import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; -import com.intellij.psi.statistics.StatisticsManager; -import com.intellij.psi.statistics.impl.StatisticsManagerImpl; import com.intellij.testFramework.PlatformTestCase; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -38,12 +36,6 @@ public abstract class CompletionTestCase extends DaemonAnalyzerTestCase { protected LookupElement[] myItems; private CompletionType myType = CompletionType.BASIC; - @Override - protected void setUp() throws Exception { - super.setUp(); - ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics(); - } - @Override protected void tearDown() throws Exception { try { diff --git a/java/testFramework/src/com/intellij/codeInsight/completion/LightCompletionTestCase.java b/java/testFramework/src/com/intellij/codeInsight/completion/LightCompletionTestCase.java index 109542da58c2..d7a89a49a4eb 100644 --- a/java/testFramework/src/com/intellij/codeInsight/completion/LightCompletionTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/completion/LightCompletionTestCase.java @@ -19,8 +19,6 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.testFramework.LightCodeInsightTestCase; -import com.intellij.psi.statistics.impl.StatisticsManagerImpl; -import com.intellij.psi.statistics.StatisticsManager; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NonNls; @@ -37,12 +35,6 @@ public abstract class LightCompletionTestCase extends LightCodeInsightTestCase { protected LookupElement[] myItems; private CompletionType myType = CompletionType.BASIC; - @Override - protected void setUp() throws Exception { - super.setUp(); - ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics(); - } - @Override protected void tearDown() throws Exception { LookupManager.getInstance(getProject()).hideActiveLookup(); diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java index e085ce9f8687..357134d2a19d 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java @@ -25,7 +25,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.vfs.VirtualFileFilter; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.testFramework.ExpectedHighlightingData; import com.intellij.testFramework.FileTreeAccessFilter; import com.intellij.testFramework.HighlightTestInfo; @@ -144,7 +144,7 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa PsiFile file = getFile(); if (editor instanceof EditorWindow) { editor = ((EditorWindow)editor).getDelegate(); - file = InjectedLanguageFacadeImpl.getTopLevelFile(file); + file = InjectedLanguageUtil.getTopLevelFile(file); } return CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, toIgnore, false); diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java index 86331a0dcfd3..155c3110e9cf 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java @@ -29,7 +29,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.rt.execution.junit.FileComparisonFailure; import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; import com.intellij.util.IncorrectOperationException; @@ -107,7 +107,7 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase } public static Pair parseActionHint(final PsiFile file, String contents, @NonNls @RegExp String actionPattern) { - PsiFile hostFile = InjectedLanguageFacadeImpl.getTopLevelFile(file); + PsiFile hostFile = InjectedLanguageUtil.getTopLevelFile(file); final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(hostFile.getLanguage()); String comment = commenter.getLineCommentPrefix(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index 0f23ddf7c810..9a0a11adbfa3 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -164,7 +164,12 @@ final class BuildSession implements Runnable, CanceledStatus { boolean forceCleanCaches = false; ProjectDescriptor pd; final Project project = loadProject(projectPath); + final File dataStorageRoot = Utils.getDataStorageRoot(project); + if (!dataStorageRoot.exists()) { + // invoked the very first time for this project. Force full rebuild + buildType = BuildType.PROJECT_REBUILD; + } final boolean inMemoryMappingsDelta = System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION) != null; ProjectTimestamps projectTimestamps = null; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index de29273874d4..1f0c39970b1a 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -161,7 +161,7 @@ public class IncProjectBuilder { } ExternalJavacDescriptor.KEY.set(context, null); } - cleanupJavacNameTable(); + //cleanupJavacNameTable(); } private static boolean ourClenupFailed = false; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java index a2f112afd57c..303f7aab6870 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java @@ -34,11 +34,6 @@ public class BuildFSState extends FSState { myAlwaysScanFS = alwaysScanFS; } - @Override - public boolean isInitialized(String moduleName) { - return myAlwaysScanFS || super.isInitialized(moduleName); - } - @Override public boolean markInitialScanPerformed(String moduleName, boolean forTests) { return myAlwaysScanFS || super.markInitialScanPerformed(moduleName, forTests); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java index 24fb0f2a61ec..44c7f3f86f16 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java @@ -133,10 +133,6 @@ public class FSState { } } - public boolean isInitialized(String moduleName) { - return myInitialTestsScanPerformed.contains(moduleName) && myInitialProductionScanPerformed.contains(moduleName); - } - public boolean markInitialScanPerformed(final String moduleName, boolean forTests) { return (forTests ? myInitialTestsScanPerformed : myInitialProductionScanPerformed).add(moduleName); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index ccc51cacea7d..49a7dce25c80 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -38,7 +38,8 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.incremental.storage.SourceToFormMapping; import org.jetbrains.jps.javac.*; -import javax.tools.*; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; @@ -809,13 +810,17 @@ public class JavaBuilder extends ModuleLevelBuilder { final Map> map = new LinkedHashMap>(); final boolean compilingTests = context.isCompilingTests(); for (Module module : chunk.getModules()) { + final String output = compilingTests ? module.getTestOutputPath() : module.getOutputPath(); + if (output == null) { + continue; + } final Set roots = new LinkedHashSet(); for (RootDescriptor descriptor : context.getModuleRoots(module)) { if (descriptor.isTestRoot == compilingTests) { roots.add(descriptor.root); } } - map.put(new File(compilingTests ? module.getTestOutputPath() : module.getOutputPath()), roots); + map.put(new File(output), roots); } return map; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java index 044ff75f2a23..60838deade3a 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java @@ -71,6 +71,9 @@ public class ResourcesBuilder extends ModuleLevelBuilder { String sourceRoot, final SourceToOutputMapping outputToSourceMapping) throws IOException { final String outputRoot = context.isCompilingTests() ? module.getTestOutputPath() : module.getOutputPath(); + if (outputRoot == null) { + return; + } final String relativePath = FileUtil.getRelativePath(sourceRoot, FileUtil.toSystemIndependentName(file.getPath()), '/'); final String prefix = module.getSourceRootPrefixes().get(sourceRoot); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java index ad5986f2a5ac..1240cd395f0e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java @@ -18,7 +18,7 @@ import java.util.Map; * Date: 10/7/11 */ public class BuildDataManager implements StorageOwner { - private static final int VERSION = 5; + private static final int VERSION = 6; private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager"); private static final String SRC_TO_OUTPUTS_STORAGE = "src-out"; private static final String SRC_TO_FORM_STORAGE = "src-form"; diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java index b051dfa52948..3f9f883799ea 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager.java @@ -6,7 +6,8 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.List; import javax.lang.model.SourceVersion; -import javax.tools.*; +import javax.tools.FileObject; +import javax.tools.JavaFileObject; import java.io.*; import java.lang.ref.SoftReference; import java.lang.reflect.Field; @@ -152,8 +153,12 @@ class OptimizedFileManager extends DefaultFileManager { private void collectFromDirectory(File directory, Set fileKinds, boolean recurse, ListBuffer result) { final File[] children = directory.listFiles(); if (children != null) { + final boolean acceptUnknownFiles = fileKinds.contains(JavaFileObject.Kind.OTHER); for (File child : children) { - if (isValidFile(child.getName(), fileKinds) && isFile(child)) { + if (isValidFile(child.getName(), fileKinds)) { + if (acceptUnknownFiles && !isFile(child)) { + continue; + } final JavaFileObject fe = new InputFileObject(child); result.append(fe); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java index d0aad87b2381..d611dc2ff14b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java @@ -8,7 +8,7 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import javax.lang.model.SourceVersion; -import javax.tools.*; +import javax.tools.JavaFileObject; import java.io.*; import java.lang.ref.Reference; import java.lang.ref.SoftReference; @@ -129,11 +129,14 @@ class OptimizedFileManager17 extends com.sun.tools.javac.file.JavacFileManager { if (sortFiles != null) { Arrays.sort(files, sortFiles); } - + final boolean acceptUnknownFiles = fileKinds.contains(JavaFileObject.Kind.OTHER); for (File f: files) { - String fileName = f.getName(); - if (isValidFile(fileName, fileKinds) && isFile(f)) { - JavaFileObject fe = new InputFileObject(this, f); + final String fileName = f.getName(); + if (isValidFile(fileName, fileKinds)) { + if (acceptUnknownFiles && !isFile(f)) { + continue; + } + final JavaFileObject fe = new InputFileObject(this, f); resultList.append(fe); } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 208716e803ed..52c02f467ff7 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -271,7 +271,7 @@ public abstract class IncrementalTestCase extends TestCase { rebuildDump.close(); - // assertEquals(rebuildDump.toString(), makeDump.toString()); + assertEquals(rebuildDump.toString(), makeDump.toString()); } } finally { diff --git a/jps/lib/optimizedFileManager.jar b/jps/lib/optimizedFileManager.jar index c3726243b6e6..7270c4d0d039 100644 Binary files a/jps/lib/optimizedFileManager.jar and b/jps/lib/optimizedFileManager.jar differ diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/IntIntMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/IntIntMultiMaplet.java index 52fbf6bd1df3..dfa667017125 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/IntIntMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/IntIntMultiMaplet.java @@ -74,10 +74,6 @@ abstract class IntIntMultiMaplet implements Streamable { for (final int a : keys) { final TIntHashSet b = get(a); - if (b.size() == 0) { - continue; - } - stream.print(" Key: "); stream.println(context.getValue(a)); stream.println(" Values:"); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/IntIntPersistentMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/IntIntPersistentMultiMaplet.java index dc9a33221319..4c1224a7c2b3 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/IntIntPersistentMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/IntIntPersistentMultiMaplet.java @@ -78,7 +78,7 @@ class IntIntPersistentMultiMaplet extends IntIntMultiMaplet { public void replace(int key, TIntHashSet value) { try { myCache.remove(key); - if (value == null) { + if (value == null || value.isEmpty()) { myMap.remove(key); } else { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/IntIntTransientMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/IntIntTransientMultiMaplet.java index 38df8b3c6708..b92bbc5d7922 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/IntIntTransientMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/IntIntTransientMultiMaplet.java @@ -56,7 +56,7 @@ class IntIntTransientMultiMaplet extends IntIntMultiMaplet { @Override public void replace(int key, TIntHashSet value) { - if (value == null) { + if (value == null || value.isEmpty()) { myMap.remove(key); } else { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectMultiMaplet.java index ea38d84bf96a..a1e71c96a268 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectMultiMaplet.java @@ -74,10 +74,6 @@ abstract class IntObjectMultiMaplet implements Streamable for (final int a : keys) { final Collection b = get(a); - if (b.size() == 0) { - continue; - } - stream.print(" Key: "); stream.println(context.getValue(a)); stream.println(" Values:"); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectPersistentMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectPersistentMultiMaplet.java index d2978f49021c..ee2a57226846 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectPersistentMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectPersistentMultiMaplet.java @@ -83,7 +83,7 @@ class IntObjectPersistentMultiMaplet extends IntObjectMult public void replace(int key, Collection value) { try { myCache.remove(key); - if (value == null) { + if (value == null || value.isEmpty()) { myMap.remove(key); } else { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectTransientMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectTransientMultiMaplet.java index 830bdae198f5..c9a8b889a441 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectTransientMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/IntObjectTransientMultiMaplet.java @@ -55,7 +55,7 @@ class IntObjectTransientMultiMaplet extends IntObjectMulti @Override public void replace(int key, Collection value) { - if (value == null) { + if (value == null || value.isEmpty()) { myMap.remove(key); } else { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 54853ecdfa64..649f26f31d91 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -1027,7 +1027,6 @@ public class Mappings { } private void processDisappearedClasses() { - myDelta.runPostPasses(); myDelta.compensateRemovedContent(myFilesToCompile); final Collection removed = myDelta.getRemovedFiles(); @@ -1920,11 +1919,18 @@ public class Mappings { return new Differential(delta, removed, filesToCompile, compiledFiles, affectedFiles, filter, constantSearch).differentiate(); } - private void cleanupBackDependency(final int className, @Nullable Collection clusters, IntIntMultiMaplet buffer) { + private void cleanupBackDependency(final int className, @Nullable Collection clusters, @Nullable Collection annotationUsages, final IntIntMultiMaplet buffer) { if (clusters == null) { final int sourceFile = myClassToSourceFile.get(className); if (sourceFile > 0) { clusters = mySourceFileToUsages.get(sourceFile); + annotationUsages = mySourceFileToAnnotationUsages.get(sourceFile); + } + } + + if (annotationUsages != null) { + for (final UsageRepr.Usage usage : annotationUsages) { + buffer.put(usage.getOwner(), className); } } @@ -1943,6 +1949,7 @@ public class Mappings { private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, final Collection clusters, + final Collection annotationUsages, final IntIntMultiMaplet dependenciesTrashBin) { final int className = cr.name; @@ -1950,7 +1957,7 @@ public class Mappings { delta.registerRemovedSuperClass(className, superSomething); } - cleanupBackDependency(className, clusters, dependenciesTrashBin); + cleanupBackDependency(className, clusters, annotationUsages, dependenciesTrashBin); myClassToClassDependency.remove(className); myClassToSubclasses.remove(className); @@ -1972,11 +1979,10 @@ public class Mappings { for (final String file : removed) { final int fileName = myContext.get(file); final Set fileClasses = (Set)mySourceFileToClasses.get(fileName); - final Collection fileUsages = mySourceFileToUsages.get(fileName); if (fileClasses != null) { for (final ClassRepr aClass : fileClasses) { - cleanupRemovedClass(delta, aClass, fileUsages, dependenciesTrashBin); + cleanupRemovedClass(delta, aClass, mySourceFileToUsages.get(fileName), mySourceFileToAnnotationUsages.get(fileName), dependenciesTrashBin); } } @@ -1986,19 +1992,21 @@ public class Mappings { } } + final TIntHashSet compiledClasses = new TIntHashSet(); + final TIntHashSet compiledFiles = new TIntHashSet(); + + delta.myClassToSourceFile.forEachEntry(new TIntIntProcedure() { + @Override + public boolean execute(final int key, final int file) { + compiledClasses.add(key); + compiledFiles.add(file); + return true; + } + }); + if (!delta.isRebuild()) { - final TIntHashSet compiledClasses = new TIntHashSet(); - - delta.myClassToSourceFile.forEachEntry(new TIntIntProcedure() { - @Override - public boolean execute(final int a, final int b) { - compiledClasses.add(a); - return true; - } - }); - for (ClassRepr repr : delta.getDeletedClasses()) { - cleanupRemovedClass(delta, repr, null, dependenciesTrashBin); + cleanupRemovedClass(delta, repr, null, null, dependenciesTrashBin); } delta.getRemovedSuperClasses().forEachEntry(new TIntObjectProcedure() { @@ -2047,11 +2055,9 @@ public class Mappings { } }); - delta.getChangedClasses().forEach(new TIntProcedure() { + compiledClasses.forEach(new TIntProcedure() { @Override public boolean execute(final int className) { - final TIntHashSet s = delta.myClassToSubclasses.get(className); - final int sourceFile = delta.myClassToSourceFile.get(className); if (sourceFile > 0) { myClassToSourceFile.put(className, sourceFile); @@ -2060,13 +2066,13 @@ public class Mappings { myClassToSourceFile.remove(className); } - cleanupBackDependency(className, null, dependenciesTrashBin); + cleanupBackDependency(className, null, null, dependenciesTrashBin); return true; } }); - delta.getChangedFiles().forEach(new TIntProcedure() { + compiledFiles.forEach(new TIntProcedure() { @Override public boolean execute(final int fileName) { final Collection classes = delta.mySourceFileToClasses.get(fileName); @@ -2094,6 +2100,7 @@ public class Mappings { else { mySourceFileToAnnotationUsages.remove(fileName); } + return true; } }); @@ -2309,7 +2316,7 @@ public class Mappings { return changed.get(); } - private static void addAllKeys(final TIntHashSet whereToAdd, IntIntMultiMaplet maplet) { + private static void addAllKeys(final TIntHashSet whereToAdd, final IntIntMultiMaplet maplet) { maplet.forEachEntry(new TIntObjectProcedure() { @Override public boolean execute(int key, TIntHashSet b) { @@ -2319,6 +2326,16 @@ public class Mappings { }); } + private static void addAllKeys(final TIntHashSet whereToAdd, final IntIntMaplet maplet) { + maplet.forEachEntry(new TIntIntProcedure() { + @Override + public boolean execute(int key, int b) { + whereToAdd.add(key); + return true; + } + }); + } + private void registerRemovedSuperClass(final int aClass, final int superClass) { assert (myRemovedSuperClasses != null); myRemovedSuperClasses.put(superClass, aClass); @@ -2389,18 +2406,18 @@ public class Mappings { myClassToSubclasses, myClassToClassDependency, mySourceFileToClasses, + myClassToSourceFile, mySourceFileToAnnotationUsages, - mySourceFileToUsages, - myClassToSourceFile + mySourceFileToUsages }; final String[] info = { "ClassToSubclasses", "ClassToClassDependency", "SourceFileToClasses", + "ClassToSourceFile", "SourceFileToAnnotationUsages", - "SourceFileToUsages", - "ClassToSourceFile" + "SourceFileToUsages" }; for (int i = 0; i < data.length; i++) { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/UsageRepr.java b/jps/model/src/org/jetbrains/ether/dependencyView/UsageRepr.java index cb0fafeb122c..aff04c1b93d5 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/UsageRepr.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/UsageRepr.java @@ -2,14 +2,12 @@ package org.jetbrains.ether.dependencyView; import com.intellij.util.io.DataExternalizer; import gnu.trove.TIntHashSet; +import gnu.trove.TIntProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.asm4.Type; import org.jetbrains.ether.RW; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.io.PrintStream; +import java.io.*; import java.util.*; /** @@ -37,7 +35,8 @@ class UsageRepr { } public static class Cluster implements RW.Savable, Streamable { - private final Map myUsageToDependenciesMap = new HashMap(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR); + private final Map myUsageToDependenciesMap = + new HashMap(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR); public Cluster() { } @@ -129,24 +128,72 @@ class UsageRepr { } @Override - public void toStream(DependencyContext context, PrintStream stream) { - //To change body of implemented methods use File | Settings | File Templates. + public void toStream(final DependencyContext context, final PrintStream stream) { + stream.println(" Cluster:"); + + final List mapped = new LinkedList (); + + for (final Map.Entry e : myUsageToDependenciesMap.entrySet()) { + final ByteArrayOutputStream bas = new ByteArrayOutputStream(); + final PrintStream s = new PrintStream(bas); + + s.println(" Usage : "); + s.print (" "); + e.getKey().toStream(context, s); + + s.println(" Residence:"); + + final List r = new LinkedList(); + + e.getValue().forEach(new TIntProcedure() { + @Override + public boolean execute(final int value) { + r.add(" " + context.getValue(value)); + return true; + } + }); + + Collections.sort(r); + + for (final String sr : r) { + s.println(sr); + } + + try { + bas.close(); + } + catch (Exception x) { + throw new RuntimeException(x); + } + + mapped.add(bas.toString()); + } + + Collections.sort(mapped); + + for (final String s : mapped) { + stream.print(s); + } } } public static abstract class Usage implements RW.Savable, Streamable { public abstract int getOwner(); - - @Override - public void toStream(DependencyContext context, PrintStream stream) { - //To change body of implemented methods use File | Settings | File Templates. - } } public static abstract class FMUsage extends Usage { public final int name; public final int owner; + abstract void kindToStream (PrintStream stream); + + @Override + public void toStream(final DependencyContext context, final PrintStream stream) { + kindToStream(stream); + stream.println(" Name : " + context.getValue(name)); + stream.println(" Owner: " + context.getValue(owner)); + } + @Override public int getOwner() { return owner; @@ -215,6 +262,16 @@ class UsageRepr { } } + protected void kindToStream(final PrintStream stream) { + stream.println("FieldUsage:"); + } + + @Override + public void toStream(final DependencyContext context, final PrintStream stream) { + super.toStream(context, stream); + stream.println(" Type: " + type.getDescr(context)); + } + @Override public void save(final DataOutput out) { save(FIELD_USAGE, out); @@ -246,6 +303,11 @@ class UsageRepr { super(context, in); } + @Override + protected void kindToStream(final PrintStream stream) { + stream.println("FieldAssignUsage:"); + } + @Override public void save(final DataOutput out) { save(FIELD_ASSIGN_USAGE, out); @@ -319,6 +381,25 @@ class UsageRepr { public int hashCode() { return ((31 * Arrays.hashCode(argumentTypes) + (returnType.hashCode())) * 31 + (name)) * 31 + (owner); } + + @Override + void kindToStream(final PrintStream stream) { + stream.println("MethodUsage:"); + } + + @Override + public void toStream(DependencyContext context, PrintStream stream) { + super.toStream(context, stream); + + stream.println(" Arguments:"); + + for (final TypeRepr.AbstractType at : argumentTypes) { + stream.println(" " + at.getDescr(context)); + } + + stream.println(" Return type:"); + stream.println(" " + returnType.getDescr(context)); + } } public static class MetaMethodUsage extends FMUsage { @@ -369,6 +450,17 @@ class UsageRepr { result = 31 * result + myArity; return result; } + + @Override + void kindToStream(final PrintStream stream) { + stream.println("MetaMethodUsage:"); + } + + @Override + public void toStream(DependencyContext context, PrintStream stream) { + super.toStream(context, stream); + stream.println(" Arity: " + Integer.toString(myArity)); + } } public static class ClassUsage extends Usage { @@ -417,6 +509,11 @@ class UsageRepr { public int hashCode() { return myClassName; } + + @Override + public void toStream(final DependencyContext context, final PrintStream stream) { + stream.println("ClassUsage: " + context.getValue(myClassName)); + } } public static class ClassExtendsUsage extends Usage { @@ -467,6 +564,11 @@ class UsageRepr { return true; } + + @Override + public void toStream(final DependencyContext context, final PrintStream stream) { + stream.println("ClassExtendsUsage: " + context.getValue(className)); + } } public static class ClassNewUsage extends ClassExtendsUsage { @@ -493,6 +595,11 @@ class UsageRepr { public int hashCode() { return className + 2; } + + @Override + public void toStream(final DependencyContext context, final PrintStream stream) { + stream.println("ClassNewUsage: " + context.getValue(className)); + } } public static class AnnotationUsage extends Usage { @@ -610,6 +717,48 @@ class UsageRepr { result = 31 * result + (usedTargets != null ? usedTargets.hashCode() : 0); return result; } + + @Override + public void toStream(final DependencyContext context, final PrintStream stream) { + stream.println(" AnnotationUsage:"); + stream.println(" Type : " + type.getDescr(context)); + + final List arguments = new LinkedList(); + + if (usedArguments != null) { + usedArguments.forEach(new TIntProcedure() { + @Override + public boolean execute(final int value) { + arguments.add(context.getValue(value)); + return true; + } + }); + } + + Collections.sort(arguments); + + final List targets = new LinkedList(); + + if (usedTargets != null) { + for (final ElemType e : usedTargets) { + targets.add(e.toString()); + } + } + + Collections.sort(targets); + + stream.println(" Arguments:"); + + for (final String s : arguments) { + stream.println(" " + s); + } + + stream.println(" Targets :"); + + for (final String s : targets) { + stream.println(" " + s); + } + } } public static Usage createFieldUsage(final DependencyContext context, final int name, final int owner, final int descr) { @@ -641,7 +790,10 @@ class UsageRepr { return context.getUsage(new ClassNewUsage(name)); } - public static Usage createAnnotationUsage(final DependencyContext context, final TypeRepr.ClassType type, final TIntHashSet usedArguments, final Set targets) { + public static Usage createAnnotationUsage(final DependencyContext context, + final TypeRepr.ClassType type, + final TIntHashSet usedArguments, + final Set targets) { return context.getUsage(new AnnotationUsage(type, usedArguments, targets)); } diff --git a/jps/model/src/org/jetbrains/jps/ProjectPaths.java b/jps/model/src/org/jetbrains/jps/ProjectPaths.java index cac4d2399d0d..56e50a76a9d7 100644 --- a/jps/model/src/org/jetbrains/jps/ProjectPaths.java +++ b/jps/model/src/org/jetbrains/jps/ProjectPaths.java @@ -104,7 +104,9 @@ public class ProjectPaths { private static void addFiles(Set files, final Collection paths) { for (String root : paths) { - files.add(new File(root)); + if (root != null) { + files.add(new File(root)); + } } } diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt index 12397d5681bc..d2d0465f9c97 100644 --- a/lib/required_for_dist.txt +++ b/lib/required_for_dist.txt @@ -37,6 +37,7 @@ picocontainer.jar resolver.jar sanselan-0.98-snapshot.jar serviceMessages.jar +snappy-java-1.0.4.1.jar trove4j.jar velocity.jar winp-1.16-patched.jar diff --git a/lib/snappy-java-1.0.4.1.jar b/lib/snappy-java-1.0.4.1.jar new file mode 100644 index 000000000000..4f2b757d7f5d Binary files /dev/null and b/lib/snappy-java-1.0.4.1.jar differ diff --git a/lib/src/snappy-java-1.0.4.1-src.zip b/lib/src/snappy-java-1.0.4.1-src.zip new file mode 100644 index 000000000000..3d2558956ce1 Binary files /dev/null and b/lib/src/snappy-java-1.0.4.1-src.zip differ diff --git a/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java b/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java index 358847d16e92..b9097c322e03 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java +++ b/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java @@ -17,15 +17,20 @@ package com.intellij.psi.stubs; import com.intellij.openapi.diagnostic.LogUtil; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.util.io.AbstractStringEnumerator; import com.intellij.util.io.DataInputOutputUtil; +import com.intellij.util.io.IOUtil; import gnu.trove.TIntObjectHashMap; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.List; /** @@ -73,8 +78,18 @@ public class StubSerializationHelper { } public void serialize(StubElement rootStub, OutputStream stream) throws IOException { - StubOutputStream stubOutputStream = new StubOutputStream(stream, myNameStorage); + BufferExposingByteArrayOutputStream out = new BufferExposingByteArrayOutputStream(); + FileLocalStringEnumerator storage = new FileLocalStringEnumerator(); + StubOutputStream stubOutputStream = new StubOutputStream(out, storage); + doSerialize(rootStub, stubOutputStream); + DataOutputStream resultStream = new DataOutputStream(stream); + DataInputOutputUtil.writeINT(resultStream, storage.myStrings.size()); + byte[] buffer = IOUtil.allocReadWriteUTFBuffer(); + for(String s:storage.myStrings) { + IOUtil.writeUTFFast(buffer, resultStream, s); + } + resultStream.write(out.getInternalBuffer(), 0, out.size()); } private int getClassId(final StubSerializer serializer) { @@ -84,7 +99,18 @@ public class StubSerializationHelper { } public StubElement deserialize(InputStream stream) throws IOException { - StubInputStream inputStream = new StubInputStream(stream, myNameStorage); + FileLocalStringEnumerator storage = new FileLocalStringEnumerator(); + StubInputStream inputStream = new StubInputStream(stream, storage); + final int size = DataInputOutputUtil.readINT(inputStream); + byte[] buffer = IOUtil.allocReadWriteUTFBuffer(); + + int i = 1; + while(i <= size) { + String s = IOUtil.readUTFFast(buffer, inputStream); + storage.myStrings.add(s); + storage.myEnumerates.put(s, i); + ++i; + } return deserialize(inputStream, null); } @@ -106,4 +132,46 @@ public class StubSerializationHelper { private StubSerializer getClassById(int id) { return myIdToSerializer.get(id); } + + private static class FileLocalStringEnumerator implements AbstractStringEnumerator { + private final TObjectIntHashMap myEnumerates = new TObjectIntHashMap(); + private final ArrayList myStrings = new ArrayList(); + + @Override + public int enumerate(@Nullable String value) throws IOException { + if (value == null) return 0; + int i = myEnumerates.get(value); + if (i == 0) { + if (myEnumerates.containsKey(value)) { + int a = 1; + } + myEnumerates.put(value, i = myStrings.size() + 1); + myStrings.add(value); + } + return i; + } + + @Override + public String valueOf(int idx) throws IOException { + if (idx == 0) return null; + return myStrings.get(idx - 1); + } + + @Override + public void markCorrupted() { + } + + @Override + public void close() throws IOException { + } + + @Override + public boolean isDirty() { + return false; + } + + @Override + public void force() { + } + } } diff --git a/platform/funcTests/config/options/feature.usage.statistics.xml b/platform/funcTests/config/options/feature.usage.statistics.xml index 9636da089d21..e047526ca94f 100644 --- a/platform/funcTests/config/options/feature.usage.statistics.xml +++ b/platform/funcTests/config/options/feature.usage.statistics.xml @@ -14,7 +14,6 @@ - @@ -57,7 +56,6 @@ - @@ -65,7 +63,6 @@ - diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java index e472a553e366..971c86136a47 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java @@ -98,4 +98,8 @@ public final class CompletionParameters { public CompletionParameters withPosition(PsiElement element, int offset) { return new CompletionParameters(element, myOriginalFile, myCompletionType, offset, myInvocationCount, myLookup); } + + public boolean isExtendedCompletion() { + return myCompletionType == CompletionType.CLASS_NAME || myCompletionType == CompletionType.BASIC && myInvocationCount >= 2; + } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java index 0a237b0e65d9..c7495e451384 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java +++ b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java @@ -35,6 +35,7 @@ import org.jetbrains.annotations.Nullable; public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction { @Override public final void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!file.getManager().isInProject(file)) return; final PsiElement element = getElement(editor, file); if (element != null) { invoke(project, editor, element); @@ -54,6 +55,7 @@ public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction @Override public final boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + if (!file.getManager().isInProject(file)) return false; final PsiElement element = getElement(editor, file); return element != null && isAvailable(project, editor, element); } @@ -71,7 +73,6 @@ public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction @Nullable protected static PsiElement getElement(Editor editor, @NotNull PsiFile file) { - if (!file.getManager().isInProject(file)) return null; CaretModel caretModel = editor.getCaretModel(); int position = caretModel.getOffset(); return file.findElementAt(position); diff --git a/platform/lang-api/src/com/intellij/formatting/DependentSpacingRule.java b/platform/lang-api/src/com/intellij/formatting/DependentSpacingRule.java new file mode 100644 index 000000000000..643e08ed1049 --- /dev/null +++ b/platform/lang-api/src/com/intellij/formatting/DependentSpacingRule.java @@ -0,0 +1,95 @@ +/* + * Copyright 2000-2012 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.formatting; + +import com.intellij.openapi.util.TextRange; +import gnu.trove.TObjectIntHashMap; +import org.jetbrains.annotations.NotNull; + +/** + * Holds settings that should be used if + * {@link Spacing#createDependentLFSpacing(int, int, TextRange, boolean, int, DependentSpacingRule) dependent spacing} + * target region changes its 'contains line feeds' status. + * + * @author Denis Zhdanov + * @since 6/28/12 1:08 PM + */ +public class DependentSpacingRule { + + enum Anchor { + MIN_LINE_FEEDS, MAX_LINE_FEEDS + } + + enum Trigger { + HAS_LINE_FEEDS, DOES_NOT_HAVE_LINE_FEEDS + } + + public static final DependentSpacingRule DEFAULT = + new DependentSpacingRule(Trigger.HAS_LINE_FEEDS).registerData(Anchor.MIN_LINE_FEEDS, 1); + + private final TObjectIntHashMap myData = new TObjectIntHashMap(); + + @NotNull private final Trigger myTrigger; + + public DependentSpacingRule(@NotNull Trigger trigger) { + myTrigger = trigger; + } + + @NotNull + public Trigger getTrigger() { + return myTrigger; + } + + /** + * Allows to register given data for the given anchor within the current rule. + * + * @param anchor target anchor + * @param data data to register for the given anchor + * @param data's type + * @see #getData(Anchor) + */ + public DependentSpacingRule registerData(@NotNull Anchor anchor, int data) { + myData.put(anchor, data); + return this; + } + + /** + * @param anchor target data anchor + * @return true if there is a data registered for the given anchor within the current rule; + * false otherwise + */ + public boolean hasData(@NotNull Anchor anchor) { + return myData.containsKey(anchor); + } + + /** + * Allows to retrieve data associated with the given anchor. + * + * @param anchor target anchor + * @param data's type + * @return data associated for the given anchor + * @throws IllegalArgumentException if no data is registered for the given anchor + * (use {@link #hasData(Anchor)} for the preliminary examination) + */ + public int getData(@NotNull Anchor anchor) throws IllegalArgumentException { + if (!myData.containsKey(anchor)) { + throw new IllegalArgumentException(String.format( + "No data is registered for the dependent spacing rule %s. Registered: %s", anchor, myData + )); + } + return myData.get(anchor); + } +} diff --git a/platform/lang-api/src/com/intellij/formatting/Spacing.java b/platform/lang-api/src/com/intellij/formatting/Spacing.java index 4077efbdc970..923370a9025b 100644 --- a/platform/lang-api/src/com/intellij/formatting/Spacing.java +++ b/platform/lang-api/src/com/intellij/formatting/Spacing.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -16,6 +16,7 @@ package com.intellij.formatting; import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; /** * The spacing setting for a formatting model block. Indicates the number of spaces and/or @@ -100,19 +101,50 @@ public abstract class Spacing { * to which the spacing setting instance is related, or Integer.MAX_VALUE * if the number of spaces is not limited. Spaces are deleted if there are * more than this amount of spaces in the document. - * @param dependance The text range checked for the presense of line breaks. + * @param dependency The text range checked for the presence of line breaks. * @param keepLineBreaks Whether the existing line breaks between the blocks should be preserved. * @param keepBlankLines Whether the existing blank lines between the blocks should be preserved. * @return the spacing setting instance. */ public static Spacing createDependentLFSpacing(int minSpaces, int maxSpaces, - TextRange dependance, + TextRange dependency, boolean keepLineBreaks, - int keepBlankLines) { - return myFactory.createDependentLFSpacing(minSpaces, maxSpaces, dependance, keepLineBreaks, keepBlankLines); + int keepBlankLines) + { + return createDependentLFSpacing(minSpaces, maxSpaces, dependency, keepLineBreaks, keepBlankLines, DependentSpacingRule.DEFAULT); } + /** + * Creates a spacing setting instance which uses settings from the given dependent spacing rule if the specified text range changes + * its 'has line feed' status during formatting (new line feed is added and the range hasn't contained them before + * or it contained line feed(s) and it was removed during formatting). + *

+ * Used for formatting rules like the "next line if wrapped" brace placement. + * + * @param minSpaces The minimum number of spaces that should be present between the blocks + * to which the spacing setting instance is related. Spaces are inserted + * if there are less than this amount of spaces in the document. + * @param maxSpaces The maximum number of spaces that should be present between the blocks + * to which the spacing setting instance is related, or Integer.MAX_VALUE + * if the number of spaces is not limited. Spaces are deleted if there are + * more than this amount of spaces in the document. + * @param dependencyRange The text range checked for the presence of line breaks. + * @param keepLineBreaks Whether the existing line breaks between the blocks should be preserved. + * @param keepBlankLines Whether the existing blank lines between the blocks should be preserved. + * @param rule settings to use if dependent region changes its 'contains line feed' status during formatting + * @return the spacing setting instance for the given parameters + */ + public static Spacing createDependentLFSpacing(int minSpaces, + int maxSpaces, + @NotNull TextRange dependencyRange, + boolean keepLineBreaks, + int keepBlankLines, + @NotNull DependentSpacingRule rule) + { + return myFactory.createDependentLFSpacing(minSpaces, maxSpaces, dependencyRange, keepLineBreaks, keepBlankLines, rule); + } + /** * Creates a spacing setting instance which preserves the presence of spaces between the blocks but, * if spaces are present, may insert or delete the spaces. Used, for example, for HTML formatting diff --git a/platform/lang-api/src/com/intellij/formatting/SpacingFactory.java b/platform/lang-api/src/com/intellij/formatting/SpacingFactory.java index 40e6f1f29f27..2c105693a68d 100644 --- a/platform/lang-api/src/com/intellij/formatting/SpacingFactory.java +++ b/platform/lang-api/src/com/intellij/formatting/SpacingFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -16,34 +16,43 @@ package com.intellij.formatting; import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; /** * Internal interface for creating spacing instances. */ interface SpacingFactory { - public Spacing createSpacing(int minSpaces, + + @NotNull + Spacing createSpacing(int minSpaces, int maxSpaces, int minLineFeeds, boolean keepLineBreaks, int keepBlankLines); - public Spacing getReadOnlySpacing(); + @NotNull + Spacing getReadOnlySpacing(); + + @NotNull + Spacing createDependentLFSpacing(int minSpaces, + int maxSpaces, + @NotNull TextRange dependencyRange, + boolean keepLineBreaks, + int keepBlankLines, + @NotNull DependentSpacingRule rule); - public Spacing createDependentLFSpacing(int minSpaces, - int maxSpaces, - TextRange dependance, - boolean keepLineBreaks, - int keepBlankLines); + @NotNull + Spacing createSafeSpacing(boolean keepLineBreaks, + int keepBlankLines); - public Spacing createSafeSpacing(boolean keepLineBreaks, - int keepBlankLines); - - public Spacing createKeepingFirstColumnSpacing(final int minSpaces, - final int maxSpaces, - final boolean keepLineBreaks, - final int keepBlankLines); + @NotNull + Spacing createKeepingFirstColumnSpacing(final int minSpaces, + final int maxSpaces, + final boolean keepLineBreaks, + final int keepBlankLines); + @NotNull Spacing createSpacing(final int minSpaces, final int maxSpaces, final int minLineFeeds, final boolean keepLineBreaks, final int keepBlankLines, final int prefLineFeeds); } diff --git a/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java b/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java index 7f7567838869..b215fad80285 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java +++ b/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java @@ -6,7 +6,6 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -132,7 +131,7 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D * @param node The node which may contain custom region start. * @return True if the node marks a custom region start. */ - protected final boolean isCustomRegionStart(ASTNode node) { + public final boolean isCustomRegionStart(ASTNode node) { if (isCustomFoldingCandidate(node)) { String nodeText = node.getText(); CustomFoldingProvider defaultProvider = getDefaultProvider(nodeText); diff --git a/platform/lang-impl/lang-impl.iml b/platform/lang-impl/lang-impl.iml index c92440432c16..44324243fa93 100644 --- a/platform/lang-impl/lang-impl.iml +++ b/platform/lang-impl/lang-impl.iml @@ -23,6 +23,7 @@ + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java index a067f7a45b44..673baa207249 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java @@ -40,7 +40,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; @@ -157,7 +157,7 @@ public class AutoPopupController implements Disposable { if (file == null) return; if (!documentManager.isUncommited(editor.getDocument())) { - file = documentManager.getPsiFile(InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(editor, file).getDocument()); + file = documentManager.getPsiFile(InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file).getDocument()); if (file == null) return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/BaseCodeInsightAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/BaseCodeInsightAction.java index d3fc7311dd0e..2a76da8174ba 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/BaseCodeInsightAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/BaseCodeInsightAction.java @@ -26,7 +26,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,7 +59,7 @@ public abstract class BaseCodeInsightAction extends CodeInsightAction { PsiFile psiFile = documentManager.getCachedPsiFile(editor.getDocument()); if (psiFile != null) { if (commit) documentManager.commitAllDocuments(); - injectedEditor = InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(editor, psiFile); + injectedEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, psiFile); } } return injectedEditor; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index dfbc027222fb..b81e09416b14 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -144,12 +144,14 @@ public class ReformatCodeAction extends AnAction implements DumbAware { boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn(); boolean processWholeFile = false; boolean processChangedTextOnly = false; - if (EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG || (file == null && dir != null)) { + final boolean showDialog = EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG; + if (showDialog || (file == null && dir != null)) { final LayoutCodeDialog dialog = new LayoutCodeDialog(project, CodeInsightBundle.message("process.reformat.code"), file, dir, hasSelection ? Boolean.TRUE : Boolean.FALSE, HELP_ID); dialog.show(); if (!dialog.isOK()) return; - EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG = !dialog.isDoNotAskMe(); + final boolean showDialogAtFuture = dir == null ? !dialog.isDoNotAskMe() : processChangedTextOnly; + EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG = showDialogAtFuture; updateShowDialogSetting(dialog, "\"Reformat Code\" dialog disabled"); optimizeImports = dialog.isOptimizeImports(); processWholeFile = dialog.isProcessWholeFile(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java index e2eb6b67dc44..c9bed0d1aea9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java @@ -22,7 +22,6 @@ import org.jetbrains.annotations.NonNls; */ public interface CodeCompletionFeatures { @NonNls String EXCLAMATION_FINISH = "editing.completion.finishByExclamation"; - @NonNls String SECOND_CLASS_NAME_COMPLETION = "editing.completion.second.classname"; @NonNls String SECOND_BASIC_COMPLETION = "editing.completion.second.basic"; @NonNls String EDITING_COMPLETION_SMARTTYPE_GENERAL = "editing.completion.smarttype.general"; @NonNls String EDITING_COMPLETION_BASIC = "editing.completion.basic"; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index f4ab7e6cd966..f6124cc309ee 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -60,7 +60,7 @@ import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.PsiFileEx; import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.impl.source.PostprocessReformattingAspect; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.reference.SoftReference; import com.intellij.util.Consumer; @@ -151,10 +151,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass(), CompletionPhase.CommittingDocuments.class); if (time > 1) { - if (myCompletionType == CompletionType.CLASS_NAME) { - FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.SECOND_CLASS_NAME_COMPLETION); - } - else if (myCompletionType == CompletionType.BASIC) { + if (myCompletionType == CompletionType.BASIC) { FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.SECOND_BASIC_COMPLETION); } } @@ -223,7 +220,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { int offset = editor.getCaretModel().getOffset(); int psiOffset = Math.max(0, offset - 1); - PsiElement elementAt = InjectedLanguageFacadeImpl.findInjectedElementNoCommit(psiFile, psiOffset); + PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(psiFile, psiOffset); if (elementAt == null) { elementAt = psiFile.findElementAt(psiOffset); } @@ -528,10 +525,10 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { } } }); - final PsiFile hostFile = InjectedLanguageFacadeImpl.getTopLevelFile(fileCopy[0]); + final PsiFile hostFile = InjectedLanguageUtil.getTopLevelFile(fileCopy[0]); final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(hostFile.getProject()); final int hostStartOffset = injectedLanguageManager.injectedToHost(fileCopy[0], initContext.getStartOffset()); - final Editor hostEditor = InjectedLanguageFacadeImpl.getTopLevelEditor(initContext.getEditor()); + final Editor hostEditor = InjectedLanguageUtil.getTopLevelEditor(initContext.getEditor()); final OffsetMap hostMap = new OffsetMap(hostEditor.getDocument()); final OffsetMap original = initContext.getOffsetMap(); @@ -595,13 +592,13 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(hostFile.getProject()); CompletionContext context; - PsiFile injected = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(hostFile, hostStartOffset); + PsiFile injected = InjectedLanguageUtil.findInjectedPsiNoCommit(hostFile, hostStartOffset); if (injected != null) { TextRange host = injectedLanguageManager.injectedToHost(injected, injected.getTextRange()); assert hostStartOffset >= host.getStartOffset() : "startOffset before injected"; assert hostStartOffset <= host.getEndOffset() : "startOffset after injected"; - EditorWindow injectedEditor = (EditorWindow)InjectedLanguageFacadeImpl + EditorWindow injectedEditor = (EditorWindow)InjectedLanguageUtil .getEditorForInjectedLanguageNoCommit(hostEditor, hostFile, hostStartOffset); assert injected == injectedEditor.getInjectedFile(); final OffsetMap map = new OffsetMap(injectedEditor.getDocument()); @@ -826,7 +823,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { } private static Runnable rememberDocumentState(final Editor _editor) { - final Editor editor = InjectedLanguageFacadeImpl.getTopLevelEditor(_editor); + final Editor editor = InjectedLanguageUtil.getTopLevelEditor(_editor); final String documentText = editor.getDocument().getText(); final int caret = editor.getCaretModel().getOffset(); final int selStart = editor.getSelectionModel().getSelectionStart(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java index 7a5b646917bc..4c53bbb1e7aa 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java @@ -67,21 +67,24 @@ public class FilePathCompletionContributor extends CompletionContributor { ProcessingContext context, @NotNull CompletionResultSet result) { final PsiReference psiReference = parameters.getPosition().getContainingFile().findReferenceAt(parameters.getOffset()); - if (getReference(psiReference) != null) { - final String shortcut = getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION); - final CompletionService service = CompletionService.getCompletionService(); - if (/*StringUtil.isEmpty(service.getAdvertisementText()) &&*/ shortcut != null) { - service.setAdvertisementText(CodeInsightBundle.message("class.completion.file.path", shortcut)); + if (getReference(psiReference) != null && parameters.getInvocationCount() == 1) { + final String shortcut = getActionShortcut(IdeActions.ACTION_CODE_COMPLETION); + if (shortcut != null) { + CompletionService.getCompletionService().setAdvertisementText(CodeInsightBundle.message("class.completion.file.path", shortcut)); } } } }); - extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider() { + CompletionProvider provider = new CompletionProvider() { @Override protected void addCompletions(@NotNull final CompletionParameters parameters, ProcessingContext context, @NotNull final CompletionResultSet _result) { + if (!parameters.isExtendedCompletion()) { + return; + } + @NotNull final CompletionResultSet result = _result.caseInsensitive(); final PsiElement e = parameters.getPosition(); final Project project = e.getProject(); @@ -94,14 +97,22 @@ public class FilePathCompletionContributor extends CompletionContributor { if (first == null) return; final FileReferenceSet set = first.getFileReferenceSet(); - String prefix = set.getPathString().substring(0, parameters.getOffset() - set.getElement().getTextRange().getStartOffset() - set.getStartInElement()); + String prefix = set.getPathString() + .substring(0, parameters.getOffset() - set.getElement().getTextRange().getStartOffset() - set.getStartInElement()); final String textBeforePosition = e.getContainingFile().getText().substring(0, parameters.getOffset()); if (!textBeforePosition.endsWith(prefix)) { final int len = textBeforePosition.length(); final String fragment = len > 100 ? textBeforePosition.substring(len - 100) : textBeforePosition; - throw new AssertionError("prefix should be some actual file string just before caret: " + prefix + "\n text=" + fragment + ";\npathString=" + set.getPathString() + ";\nelementText=" + e.getParent().getText()); + throw new AssertionError("prefix should be some actual file string just before caret: " + + prefix + + "\n text=" + + fragment + + ";\npathString=" + + set.getPathString() + + ";\nelementText=" + + e.getParent().getText()); } - + List pathPrefixParts = null; int lastSlashIndex; if ((lastSlashIndex = prefix.lastIndexOf('/')) != -1) { @@ -141,7 +152,8 @@ public class FilePathCompletionContributor extends CompletionContributor { final VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile != null && virtualFile.isValid() && virtualFile != contextFile) { if (contextHelper.isMine(project, virtualFile)) { - if (pathPrefixParts == null || fileMatchesPathPrefix(contextHelper.getPsiFileSystemItem(project, virtualFile), pathPrefixParts)) { + if (pathPrefixParts == null || + fileMatchesPathPrefix(contextHelper.getPsiFileSystemItem(project, virtualFile), pathPrefixParts)) { __result.addElement(new FilePathLookupItem(file, contextHelper)); } } @@ -153,22 +165,24 @@ public class FilePathCompletionContributor extends CompletionContributor { } if (set.getSuitableFileTypes().length > 0 && parameters.getInvocationCount() == 1) { - final String shortcut = getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION); - final CompletionService service = CompletionService.getCompletionService(); + final String shortcut = getActionShortcut(IdeActions.ACTION_CODE_COMPLETION); if (shortcut != null) { - service.setAdvertisementText(CodeInsightBundle.message("class.completion.file.path.all.variants", shortcut)); + CompletionService.getCompletionService() + .setAdvertisementText(CodeInsightBundle.message("class.completion.file.path.all.variants", shortcut)); } } if (fileReferencePair.getSecond()) result.stopHere(); } } - }); + }; + extend(CompletionType.CLASS_NAME, psiElement(), provider); + extend(CompletionType.BASIC, psiElement(), provider); } private static boolean filenameMatchesPrefixOrType(final String fileName, final String prefix, final FileType[] suitableFileTypes, final int invocationCount) { final boolean prefixMatched = prefix.length() == 0 || StringUtil.startsWithIgnoreCase(fileName, prefix); - if (prefixMatched && (suitableFileTypes.length == 0 || invocationCount > 1)) return true; + if (prefixMatched && (suitableFileTypes.length == 0 || invocationCount > 2)) return true; if (prefixMatched) { final String extension = FileUtil.getExtension(fileName); @@ -293,7 +307,9 @@ public class FilePathCompletionContributor extends CompletionContributor { final Pair fileReferencePair = getReference(psiReference); LOG.assertTrue(fileReferencePair != null); - fileReferencePair.getFirst().bindToElement(myFile, true); + FileReference ref = fileReferencePair.getFirst(); + context.setTailOffset(ref.getRangeInElement().getEndOffset() + ref.getElement().getTextRange().getStartOffset()); + ref.bindToElement(myFile, true); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index baff2b619c87..2d8c4eb47a3f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -31,7 +31,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.Weigher; import com.intellij.psi.WeighingService; import com.intellij.psi.impl.DebugUtil; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -140,7 +140,7 @@ public class CompletionServiceImpl extends CompletionService{ PsiFile positionFile = myParameters.getPosition().getContainingFile(); LOG.error("prefix should be some actual file string just before caret: " + matcher.getPrefix() + "\n text=" + fragment + - "\ninjected=" + (InjectedLanguageFacadeImpl.getTopLevelFile(positionFile) != positionFile) + + "\ninjected=" + (InjectedLanguageUtil.getTopLevelFile(positionFile) != positionFile) + "\nlang=" + positionFile.getLanguage()); } return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, matcher, myContributor, myParameters, mySorter, myProcess, this); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CodeFoldingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CodeFoldingPass.java index ae9bcb6a03fa..444f8828fb4b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CodeFoldingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CodeFoldingPass.java @@ -25,7 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; class CodeFoldingPass extends TextEditorHighlightingPass implements DumbAware { @@ -72,7 +72,7 @@ class CodeFoldingPass extends TextEditorHighlightingPass implements DumbAware { } } - if (InjectedLanguageFacadeImpl.getTopLevelFile(myFile) == myFile) { + if (InjectedLanguageUtil.getTopLevelFile(myFile) == myFile) { clearFirstTimeFlag(myFile, myEditor, THE_FIRST_TIME); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index 0ca02cd407d6..b5028078cb51 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -59,7 +59,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.Problem; import com.intellij.problems.WolfTheProblemSolver; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.impl.source.tree.injected.Place; import com.intellij.psi.search.PsiTodoSearchHelper; import com.intellij.psi.search.TodoItem; @@ -291,7 +291,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP @NotNull final List elements2, @NotNull final ProgressIndicator progress, @NotNull final Set outInjected) { - List injected = InjectedLanguageFacadeImpl.getCachedInjectedDocuments(myFile); + List injected = InjectedLanguageUtil.getCachedInjectedDocuments(myFile); Collection hosts = new THashSet(elements1.size() + elements2.size() + injected.size()); //rehighlight all injected PSI regardless the range, @@ -325,7 +325,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP @Override public boolean process(PsiElement element) { progress.checkCanceled(); - InjectedLanguageFacadeImpl.enumerate(element, myFile, false, visitor); + InjectedLanguageUtil.enumerate(element, myFile, false, visitor); return true; } })) { @@ -347,7 +347,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP public boolean process(final PsiFile injectedPsi) { DocumentWindow documentWindow = (DocumentWindow)PsiDocumentManager.getInstance(myProject).getCachedDocument(injectedPsi); if (documentWindow == null) return true; - Place places = InjectedLanguageFacadeImpl.getShreds(injectedPsi); + Place places = InjectedLanguageUtil.getShreds(injectedPsi); for (PsiLanguageInjectionHost.Shred place : places) { TextRange textRange = place.getRangeInsideHost().shiftRight(place.getHost().getTextRange().getStartOffset()); if (textRange.isEmpty()) continue; @@ -503,7 +503,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP } private void highlightInjectedSyntax(final PsiFile injectedPsi, HighlightInfoHolder holder) { - List, TextRange>> tokens = InjectedLanguageFacadeImpl + List, TextRange>> tokens = InjectedLanguageUtil .getHighlightTokens(injectedPsi); if (tokens == null) return; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java index 997e08fc62af..14ed8a677812 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java @@ -382,6 +382,15 @@ public class HighlightInfo implements Segment { htmlEscapeToolTip(message), type.getSeverity(element), false, Boolean.FALSE, false); } + public static HighlightInfo createHighlightInfo(@NotNull final HighlightInfoType type, + @NotNull final PsiElement element, + @Nullable final String message, + @Nullable final TextAttributesKey attributesKey) { + TextRange textRange = element.getTextRange(); + // do not use HighlightInfoFilter + return new HighlightInfo(null, attributesKey, type, textRange.getStartOffset(), textRange.getEndOffset(), message, + htmlEscapeToolTip(message), type.getSeverity(element), false, Boolean.FALSE, false); + } public static HighlightInfo fromAnnotation(@NotNull Annotation annotation) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java index b52c21cf28a6..2012c5c95773 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java @@ -37,7 +37,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.util.Processor; @@ -100,7 +100,7 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass { if (myTarget == null) { if (!PsiDocumentManager.getInstance(myProject).isUncommited(myEditor.getDocument())) { // when document is committed, try to check injected stuff - it's fast - Editor injectedEditor = InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(myEditor, myFile, myCaretOffset); + Editor injectedEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, myFile, myCaretOffset); if (injectedEditor != null) { myTarget = TargetElementUtilBase.getInstance().findTargetElement(injectedEditor, flags, injectedEditor.getCaretModel().getOffset()); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java index e961ecd989ff..07d4c0672e26 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java @@ -47,7 +47,7 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Function; import com.intellij.util.FunctionUtil; import gnu.trove.THashSet; @@ -211,7 +211,7 @@ public class LineMarkersPass extends ProgressableTextEditorHighlightingPass impl } }; for (int i = 0, size = elements.size(); i < size; ++i) { - InjectedLanguageFacadeImpl.enumerate(elements.get(i), file, false, collectingVisitor); + InjectedLanguageUtil.enumerate(elements.get(i), file, false, collectingVisitor); } for (PsiFile injectedPsi : injectedFiles) { final Project project = injectedPsi.getProject(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index b3f706976e75..93126fa3acda 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -53,7 +53,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.profile.codeInspection.SeverityProvider; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Function; import com.intellij.util.Processor; @@ -419,7 +419,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass final boolean inVisibleRange, final boolean checkDumbAwareness, final List wrappers) { final Set injected = new THashSet(); for (PsiElement element : elements) { - InjectedLanguageFacadeImpl.enumerate(element, myFile, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() { + InjectedLanguageUtil.enumerate(element, myFile, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { injected.add(injectedPsi); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java index bad2d1853659..70d351d6092e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QuickFixAction.java @@ -29,7 +29,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -145,8 +145,8 @@ public final class QuickFixAction { PsiFile fileToUse; if (info.fromInjection) { if (injectedEditor == null) { - injectedFile = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(file, offset); - injectedEditor = InjectedLanguageFacadeImpl.getInjectedEditorForInjectedFile(editor, injectedFile); + injectedFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset); + injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile); } editorToUse = injectedEditor; fileToUse = injectedFile; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java index d1ae61a6bcdd..7bbe8596b929 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DockablePopupManager.java @@ -24,7 +24,6 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.AsyncResult; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowType; @@ -32,7 +31,7 @@ import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.content.*; import com.intellij.util.ui.update.Activatable; @@ -174,7 +173,7 @@ public abstract class DockablePopupManager { final PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, myProject); - final Editor injectedEditor = InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(editor, file); + final Editor injectedEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file); if (injectedEditor != null) { final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(injectedEditor, myProject); if (psiFile != null) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index 282890eec51a..d0a8ae4db1c3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -31,7 +31,7 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; /** @@ -83,16 +83,16 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { if (editor.isDisposed()) return; // retrieve the injected file from scratch since our typing might have destroyed the old one completely - Editor topLevelEditor = InjectedLanguageFacadeImpl.getTopLevelEditor(editor); + Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(editor); PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(topLevelEditor.getDocument()); if (file == null) return; - PsiFile topLevelFile = InjectedLanguageFacadeImpl.getTopLevelFile(file); + PsiFile topLevelFile = InjectedLanguageUtil.getTopLevelFile(file); if (!PsiDocumentManager.getInstance(project).isCommitted(editor.getDocument())) { LOG.error("Non-committed document"); PsiDocumentManager.getInstance(project).commitAllDocuments(); } - Editor newEditor = InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(topLevelEditor, topLevelFile); + Editor newEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(topLevelEditor, topLevelFile); try { new CodeCompletionHandlerBase(completionType, false, autopopup, false).invokeCompletion(project, newEditor, time, false); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java index 04b49b51046c..7bc43282dcdc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java @@ -32,7 +32,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; @@ -52,7 +52,7 @@ public class SelectWordHandler extends EditorActionHandler { LOG.debug("enter: execute(editor='" + editor + "')"); } if (editor instanceof EditorWindow && editor.getSelectionModel().hasSelection() - && InjectedLanguageFacadeImpl.isSelectionIsAboutToOverflowInjectedFragment((EditorWindow)editor)) { + && InjectedLanguageUtil.isSelectionIsAboutToOverflowInjectedFragment((EditorWindow)editor)) { // selection about to spread beyond injected fragment editor = ((EditorWindow)editor).getDelegate(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java index a9f107fd2935..a9261cc8d532 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java @@ -50,7 +50,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtilBase; @@ -270,10 +270,10 @@ public class TypedHandler extends TypedActionHandlerBase { // even for uncommitted document try to retrieve injected fragment that has been there recently // we are assuming here that when user is (even furiously) typing, injected language would not change // and thus we can use its lexer to insert closing braces etc - for (DocumentWindow documentWindow : InjectedLanguageFacadeImpl.getCachedInjectedDocuments(oldFile)) { + for (DocumentWindow documentWindow : InjectedLanguageUtil.getCachedInjectedDocuments(oldFile)) { if (documentWindow.isValid() && documentWindow.containsRange(offset, offset)) { PsiFile injectedFile = PsiDocumentManager.getInstance(oldFile.getProject()).getPsiFile(documentWindow); - final Editor injectedEditor = InjectedLanguageFacadeImpl.getInjectedEditorForInjectedFile(editor, injectedFile); + final Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile); // IDEA-52375 fix: last quote sign should be handled by outer language quote handler final CharSequence charsSequence = editor.getDocument().getCharsSequence(); if (injectedEditor.getCaretModel().getOffset() == injectedEditor.getDocument().getTextLength() && diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java index e233872ba2d4..51cf80b83161 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java @@ -34,7 +34,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.ParameterizedCachedValue; @@ -151,7 +151,7 @@ public class FoldingUpdate { Object lastTimeStamp = editor.getUserData(LAST_UPDATE_INJECTED_STAMP_KEY); if (lastTimeStamp instanceof Long && ((Long)lastTimeStamp).longValue() == timeStamp) return null; - List injectedDocuments = InjectedLanguageFacadeImpl.getCachedInjectedDocuments(file); + List injectedDocuments = InjectedLanguageUtil.getCachedInjectedDocuments(file); if (injectedDocuments.isEmpty()) return null; final List injectedEditors = new ArrayList(); final List injectedFiles = new ArrayList(); @@ -159,7 +159,7 @@ public class FoldingUpdate { for (DocumentWindow injectedDocument : injectedDocuments) { PsiFile injectedFile = PsiDocumentManager.getInstance(project).getPsiFile(injectedDocument); if (injectedFile == null || !injectedFile.isValid() || !injectedDocument.isValid()) continue; - Editor injectedEditor = InjectedLanguageFacadeImpl.getInjectedEditorForInjectedFile(editor, injectedFile); + Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile); if (!(injectedEditor instanceof EditorWindow)) continue; injectedEditors.add((EditorWindow)injectedEditor); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/OffsetsElementSignatureProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/OffsetsElementSignatureProvider.java index 35a75cf476b0..f1e78494c8a7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/OffsetsElementSignatureProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/OffsetsElementSignatureProvider.java @@ -18,7 +18,7 @@ package com.intellij.codeInsight.folding.impl; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -87,7 +87,7 @@ public class OffsetsElementSignatureProvider extends AbstractElementSignaturePro } if (result == null) { - final PsiElement injectedStartElement = InjectedLanguageFacadeImpl.findElementAtNoCommit(file, start); + final PsiElement injectedStartElement = InjectedLanguageUtil.findElementAtNoCommit(file, start); if (processingInfoStorage != null) { processingInfoStorage.append(String.format( "Trying to find injected element starting from the '%s'%s%n", diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java index d58ad07377c2..24e619be216d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java @@ -52,7 +52,7 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.Alarm; @@ -136,7 +136,7 @@ public class BraceHighlightingHandler { public void run() { try { if (!isReallyDisposed(editor, project)) { - Editor newEditor = InjectedLanguageFacadeImpl.getInjectedEditorForInjectedFile(editor, injected); + Editor newEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injected); BraceHighlightingHandler handler = new BraceHighlightingHandler(project, newEditor, alarm, injected); processor.process(handler); } @@ -161,7 +161,7 @@ public class BraceHighlightingHandler { Document document = editor.getDocument(); // when document is committed, try to highlight braces in injected lang - it's fast if (!PsiDocumentManager.getInstance(project).isUncommited(document)) { - final PsiElement injectedElement = InjectedLanguageFacadeImpl.findInjectedElementNoCommit(psiFile, offset); + final PsiElement injectedElement = InjectedLanguageUtil.findInjectedElementNoCommit(psiFile, offset); if (injectedElement != null /*&& !(injectedElement instanceof PsiWhiteSpace)*/) { final PsiFile injected = injectedElement.getContainingFile(); if (injected != null) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java index c0d1376c94cb..255f2353d97e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightManagerImpl.java @@ -41,7 +41,7 @@ import com.intellij.openapi.util.UserDataHolderEx; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -167,7 +167,7 @@ public class HighlightManagerImpl extends HighlightManager implements ProjectCom PsiFile containingFile = element.getContainingFile(); Project project = element.getProject(); // each reference can reside in its own injected editor - Editor textEditor = InjectedLanguageFacadeImpl.openEditorFor(containingFile, project); + Editor textEditor = InjectedLanguageUtil.openEditorFor(containingFile, project); if (textEditor != null) { addOccurrenceHighlight(textEditor, start, end, attributes, flags, outHighlighters, scrollmarkColor); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java index d690edf18225..b5759a2d63a9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java @@ -36,7 +36,7 @@ import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Iconable; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilBase; import gnu.trove.THashSet; import gnu.trove.TObjectHashingStrategy; @@ -112,7 +112,7 @@ class IntentionListStep implements ListPopupStep } else { hostElement = myFile.getViewProvider().findElementAt(fileOffset, myFile.getLanguage()); - element = InjectedLanguageFacadeImpl.findElementAtNoCommit(myFile, fileOffset); + element = InjectedLanguageUtil.findElementAtNoCommit(myFile, fileOffset); } PsiFile injectedFile; Editor injectedEditor; @@ -122,7 +122,7 @@ class IntentionListStep implements ListPopupStep } else { injectedFile = element.getContainingFile(); - injectedEditor = InjectedLanguageFacadeImpl.getInjectedEditorForInjectedFile(myEditor, injectedFile); + injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(myEditor, injectedFile); } boolean result = true; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java index a109226d8b82..669995440426 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java @@ -24,7 +24,7 @@ import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; @@ -58,7 +58,7 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction { final PsiLanguageInjectionHost host = PsiTreeUtil.getParentOfType(file.findElementAt(offset), PsiLanguageInjectionHost.class, false); if (host == null) return null; - final List> injections = InjectedLanguageFacadeImpl.getInstance().getInjectedPsiFiles(host); + final List> injections = InjectedLanguageUtil.getInstance().getInjectedPsiFiles(host); if (injections == null || injections.isEmpty()) return null; final int offsetInElement = offset - host.getTextRange().getStartOffset(); final Pair rangePair = ContainerUtil.find(injections, new Condition>() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java index 814bad1e40dd..1a8b9ba856d2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java @@ -48,7 +48,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.resolve.FileContextUtil; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.impl.source.tree.injected.Place; import com.intellij.testFramework.LightVirtualFile; import com.intellij.ui.awt.RelativePoint; @@ -86,7 +86,7 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable { myEditor = editor; myAction = action; myOrigDocument = editor.getDocument(); - final Place shreds = InjectedLanguageFacadeImpl.getShreds(myInjectedFile); + final Place shreds = InjectedLanguageUtil.getShreds(myInjectedFile); final FileType fileType = injectedFile.getFileType(); final Language language = injectedFile.getLanguage(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java index 4421b4d39641..b93aeb096594 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/ShowIntentionActionsHandler.java @@ -40,7 +40,7 @@ import com.intellij.psi.PsiCodeFragment; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.PairProcessor; import org.jetbrains.annotations.NotNull; @@ -56,7 +56,7 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler { PsiDocumentManager.getInstance(project).commitAllDocuments(); if (editor instanceof EditorWindow) { editor = ((EditorWindow)editor).getDelegate(); - file = InjectedLanguageFacadeImpl.getTopLevelFile(file); + file = InjectedLanguageUtil.getTopLevelFile(file); } final LookupEx lookup = LookupManager.getActiveLookup(editor); @@ -122,9 +122,9 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler { PsiFile fileToApply = null; int offset = hostEditor.getCaretModel().getOffset(); - PsiFile injectedFile = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(hostFile, offset); + PsiFile injectedFile = InjectedLanguageUtil.findInjectedPsiNoCommit(hostFile, offset); if (injectedFile != null) { - Editor injectedEditor = InjectedLanguageFacadeImpl.getInjectedEditorForInjectedFile(hostEditor, injectedFile); + Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(hostEditor, injectedFile); if (predicate.process(injectedFile, injectedEditor)) { editorToApply = injectedEditor; fileToApply = injectedFile; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupManager.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupManager.java index cde7df077e25..a1a95fd65e09 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupManager.java @@ -19,7 +19,7 @@ package com.intellij.codeInsight.lookup; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,7 +41,7 @@ public abstract class LookupManager { final LookupEx lookup = getInstance(project).getActiveLookup(); if (lookup == null) return null; - return InjectedLanguageFacadeImpl.getTopLevelEditor(lookup.getEditor()) == InjectedLanguageFacadeImpl.getTopLevelEditor(editor) ? lookup : null; + return InjectedLanguageUtil.getTopLevelEditor(lookup.getEditor()) == InjectedLanguageUtil.getTopLevelEditor(editor) ? lookup : null; } @Nullable diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index 6ae8ea014d38..a9010dac1ca5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -60,7 +60,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.searches.DefinitionsSearch; import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.LightweightHint; @@ -154,7 +154,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent { Point point = new Point(mouseEvent.getPoint()); if (PsiDocumentManager.getInstance(myProject).isCommitted(editor.getDocument())) { // when document is committed, try to check injected stuff - it's fast - editor = InjectedLanguageFacadeImpl + editor = InjectedLanguageUtil .getEditorForInjectedLanguageNoCommit(editor, psiFile, editor.logicalPositionToOffset(editor.xyToLogicalPosition(point))); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java index 925052258b1d..656946038734 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java @@ -25,7 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -55,11 +55,11 @@ public class CustomTemplateCallback { PsiDocumentManager.getInstance(myProject).commitAllDocuments(); int offset = getOffset(wrapping, editor); - PsiElement element = InjectedLanguageFacadeImpl.findInjectedElementNoCommit(file, offset); + PsiElement element = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset); myFile = element != null ? element.getContainingFile() : file; myInInjectedFragment = InjectedLanguageManager.getInstance(myProject).isInjectedFragment(myFile); - myEditor = myInInjectedFragment ? InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(editor, file, offset) : editor; + myEditor = myInInjectedFragment ? InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file, offset) : editor; fixInitialState(wrapping); } @@ -164,7 +164,7 @@ public class CustomTemplateCallback { public static PsiElement getContext(@NotNull PsiFile file, int offset) { PsiElement element = null; if (!InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) { - element = InjectedLanguageFacadeImpl.findInjectedElementNoCommit(file, offset); + element = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset); } if (element == null) { element = file.findElementAt(offset); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java index 2f2bb9a22488..74caa88a2bb1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java @@ -32,7 +32,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; @@ -60,7 +60,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { private static final Logger LOG = Logger.getInstance("#" + TemplateBuilderImpl.class.getName()); public TemplateBuilderImpl(@NotNull PsiElement element) { - myFile = InjectedLanguageFacadeImpl.getTopLevelFile(element); + myFile = InjectedLanguageUtil.getTopLevelFile(element); myDocument = myFile.getViewProvider().getDocument(); myContainerElement = wrapElement(element); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java index 85d9534bf46d..86798bb39e6e 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java @@ -26,7 +26,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.pom.Navigatable; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -142,7 +142,7 @@ public class ProblemDescriptorImpl extends CommonProblemDescriptorImpl implement if (psiElement == null) return -1; if (!psiElement.isValid()) return -1; LOG.assertTrue(psiElement.isPhysical()); - PsiFile containingFile = InjectedLanguageFacadeImpl.getTopLevelFile(psiElement); + PsiFile containingFile = InjectedLanguageUtil.getTopLevelFile(psiElement); Document document = PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(containingFile); if (document == null) return -1; TextRange textRange = getTextRange(); diff --git a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java index 6a092226235b..d91716cc0691 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java @@ -38,6 +38,7 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.ui.popup.list.PopupListElementRenderer; +import com.intellij.ui.speedSearch.SpeedSearch; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -163,7 +164,14 @@ public class ChooseRunConfigurationAction extends AnAction { popup.registerAction("deleteConfiguration_bksp", KeyStroke.getKeyStroke("BACK_SPACE"), new AbstractAction() { public void actionPerformed(ActionEvent e) { - popup.removeSelected(); + SpeedSearch speedSearch = popup.getSpeedSearch(); + if (speedSearch.isHoldingFilter()) { + speedSearch.backspace(); + speedSearch.update(); + } + else { + popup.removeSelected(); + } } }); diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java index ae9624772796..f8089fc12254 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java @@ -229,7 +229,11 @@ public class GridCellImpl implements GridCell { @Nullable private static TabInfo updatePresentation(TabInfo info, Content content) { if (info == null) return info; - return info.setIcon(content.getIcon()).setText(content.getDisplayName()).setActions(content.getActions(), content.getPlace()); + return info. + setIcon(content.getIcon()). + setText(content.getDisplayName()). + setActionsContextComponent(content.getActionsContextComponent()). + setActions(content.getActions(), content.getPlace()); } public ActionCallback select(final Content content, final boolean requestFocus) { diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java index 146d03a1a1d9..fae0f9ee875a 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java @@ -29,7 +29,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaOwner; import com.intellij.psi.meta.PsiPresentableMetaData; @@ -131,7 +131,7 @@ public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, Typ Collection refs; // in case of injected file, use host file to highlight all occurrences of the target in each injected file - PsiFile context = InjectedLanguageFacadeImpl.getTopLevelFile(file); + PsiFile context = InjectedLanguageUtil.getTopLevelFile(file); SearchScope searchScope = new LocalSearchScope(context); if (handler != null) { refs = handler.findReferencesToHighlight(target, searchScope); diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java index 77908a96df12..aff90ee6e4fc 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java @@ -16,8 +16,10 @@ package com.intellij.formatting; +import com.intellij.lang.Language; import com.intellij.openapi.util.TextRange; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -36,31 +38,45 @@ public abstract class AbstractBlockWrapper { Indent.Type.NORMAL, Indent.Type.CONTINUATION, Indent.Type.CONTINUATION_WITHOUT_FIRST )); - protected WhiteSpace myWhiteSpace; + protected WhiteSpace myWhiteSpace; protected CompositeBlockWrapper myParent; - protected int myStart; - protected int myEnd; - protected int myFlags; + protected int myStart; + protected int myEnd; + protected int myFlags; static int CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT = 1; - static int INCOMPLETE = 2; + static int INCOMPLETE = 2; + + private final Language myLanguage; protected IndentInfo myIndentFromParent = null; - private IndentImpl myIndent = null; + private IndentImpl myIndent = null; private AlignmentImpl myAlignment; - private WrapImpl myWrap; + private WrapImpl myWrap; - public AbstractBlockWrapper(final Block block, final WhiteSpace whiteSpace, final CompositeBlockWrapper parent, final TextRange textRange) { + public AbstractBlockWrapper(final Block block, + final WhiteSpace whiteSpace, + final CompositeBlockWrapper parent, + final TextRange textRange) { myWhiteSpace = whiteSpace; myParent = parent; myStart = textRange.getStartOffset(); myEnd = textRange.getEndOffset(); - myFlags = CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT | (block.isIncomplete() ? INCOMPLETE:0); + myFlags = CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT | (block.isIncomplete() ? INCOMPLETE : 0); myAlignment = (AlignmentImpl)block.getAlignment(); myWrap = (WrapImpl)block.getWrap(); + myLanguage = deriveLanguage(block); } + @Nullable + private static Language deriveLanguage(@NotNull Block block) { + if (block instanceof BlockEx) { + return ((BlockEx)block).getLanguage(); + } + return null; + } + public WhiteSpace getWhiteSpace() { return myWhiteSpace; } @@ -89,6 +105,20 @@ public abstract class AbstractBlockWrapper { return myEnd - myStart; } + /** + * There is a possible case that particular block's language differs from the language implied by the file type. We need to + * distinguish such a situation because, for example in case of indent calculation (code style settings for different languages + * may have different indent values). + *

+ * This method allows to retrieve the language associated with the current block (if provided). + * + * @return current block's language (if provided) + */ + @Nullable + public Language getLanguage() { + return myLanguage; + } + /** * Applies given start offset to the current block wrapper and recursively calls this method on parent block wrapper * if it starts at the same place as the current one. diff --git a/platform/lang-impl/src/com/intellij/formatting/BlockEx.java b/platform/lang-impl/src/com/intellij/formatting/BlockEx.java new file mode 100644 index 000000000000..9a5825dac249 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/formatting/BlockEx.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2012 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.formatting; + +import com.intellij.lang.Language; +import org.jetbrains.annotations.Nullable; + +/** + * @author Denis Zhdanov + * @since 6/26/12 11:22 AM + */ +public interface BlockEx extends Block { + + /** + * @return current block's language (is used to decide on what code style settings should be used for it) + */ + @Nullable + Language getLanguage(); +} diff --git a/platform/lang-impl/src/com/intellij/formatting/DependantSpacingImpl.java b/platform/lang-impl/src/com/intellij/formatting/DependantSpacingImpl.java index 9290989ca6bf..b1d9304ae599 100644 --- a/platform/lang-impl/src/com/intellij/formatting/DependantSpacingImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/DependantSpacingImpl.java @@ -17,6 +17,7 @@ package com.intellij.formatting; import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; /** * Extends {@link SpacingImpl} in order to add notion of dependency range. @@ -24,29 +25,50 @@ import com.intellij.openapi.util.TextRange; * 'Dependency' here affect {@link #getMinLineFeeds() minLineFieeds} property value. See property contract for more details. */ public class DependantSpacingImpl extends SpacingImpl { - private final TextRange myDependency; - private static final int DEPENDENCE_CONTAINS_LF_MASK = 0x10; + private static final int DEPENDENCE_CONTAINS_LF_MASK = 0x10; private static final int DEPENDENT_REGION_LF_CHANGED_MASK = 0x20; + @NotNull private final TextRange myDependency; + @NotNull private final DependentSpacingRule myRule; + + public DependantSpacingImpl(final int minSpaces, final int maxSpaces, - TextRange dependency, + @NotNull TextRange dependency, final boolean keepLineBreaks, - final int keepBlankLines) { + final int keepBlankLines, + @NotNull DependentSpacingRule rule) + { super(minSpaces, maxSpaces, 0, false, false, keepLineBreaks, keepBlankLines, false, 0); myDependency = dependency; + myRule = rule; } /** * @return 1 if dependency has line feeds; 0 otherwise */ public int getMinLineFeeds() { - if ((myFlags & DEPENDENCE_CONTAINS_LF_MASK) != 0) { - return 1; + if (!isTriggered()) { + return super.getMinLineFeeds(); } - else { - return 0; + + if (myRule.hasData(DependentSpacingRule.Anchor.MIN_LINE_FEEDS)) { + return myRule.getData(DependentSpacingRule.Anchor.MIN_LINE_FEEDS); } + + if (myRule.hasData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS)) { + return myRule.getData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS); + } + return super.getMinLineFeeds(); + } + + @Override + public int getKeepBlankLines() { + if (!isTriggered() || !myRule.hasData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS)) { + return super.getKeepBlankLines(); + } + + return 0; } public void refresh(FormatProcessor formatter) { @@ -58,14 +80,16 @@ public class DependantSpacingImpl extends SpacingImpl { else myFlags &= ~DEPENDENCE_CONTAINS_LF_MASK; } + @NotNull public TextRange getDependency() { return myDependency; } /** - * Allows to answer whether the target dependent regions has been changed during formatting. + * Allows to answer whether 'contains line feed' status has been changed for the target dependent region during formatting. * - * @return true if target dependent region has been changed during formatting; false otherwise + * @return true if target 'contains line feed' status has been changed for the target dependent region during formatting; + * false otherwise */ public final boolean isDependentRegionChanged() { return (myFlags & DEPENDENT_REGION_LF_CHANGED_MASK) != 0; @@ -85,4 +109,9 @@ public class DependantSpacingImpl extends SpacingImpl { return ""; } + + private boolean isTriggered() { + return myRule.getTrigger() == DependentSpacingRule.Trigger.HAS_LINE_FEEDS + ^ (myFlags & DEPENDENCE_CONTAINS_LF_MASK) == 0; + } } diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index baf5f788838c..246b4cfd8915 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -16,6 +16,7 @@ package com.intellij.formatting; +import com.intellij.lang.Language; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.TextChange; @@ -42,7 +43,7 @@ class FormatProcessor { ALIGNMENT_PROCESSORS.put(Alignment.Anchor.LEFT, new LeftEdgeAlignmentProcessor()); ALIGNMENT_PROCESSORS.put(Alignment.Anchor.RIGHT, new RightEdgeAlignmentProcessor()); } - + /** * There is a possible case that formatting introduced big number of changes to the underlying document. That number may be * big enough for that their subsequent appliance is much slower than direct replacing of the whole document text. @@ -50,7 +51,7 @@ class FormatProcessor { * Current constant holds minimum number of changes that should trigger such 'replace whole text' optimization. */ private static final int BULK_REPLACE_OPTIMIZATION_CRITERIA = 3000; - + private static final Logger LOG = Logger.getInstance("#com.intellij.formatting.FormatProcessor"); private LeafBlockWrapper myCurrentBlock; @@ -59,9 +60,9 @@ class FormatProcessor { private CompositeBlockWrapper myRootBlockWrapper; private TIntObjectHashMap myTextRangeToWrapper; - private final CommonCodeStyleSettings.IndentOptions myIndentOption; - private final CodeStyleSettings mySettings; - private final Document myDocument; + private final CommonCodeStyleSettings.IndentOptions myDefaultIndentOption; + private final CodeStyleSettings mySettings; + private final Document myDocument; /** * Remembers mappings between backward-shifted aligned block and blocks that cause that shift in order to detect @@ -82,7 +83,7 @@ class FormatProcessor { private final Map> myBackwardShiftedAlignedBlocks = new HashMap>(); - private final Map> myAlignmentMappings + private final Map> myAlignmentMappings = new HashMap>(); /** @@ -107,7 +108,7 @@ class FormatProcessor { *

    *       int[] data = {1, 2, 3};
    * 
- * We want to keep that in one line with possible but place curly braces on separate lines if the width is not enough: + * We want to keep that in one line if possible but place curly braces on separate lines if the width is not enough: *
    *      int[] data = {    | < right margin
    *          1, 2, 3       |
@@ -140,11 +141,11 @@ class FormatProcessor {
   private final HashSet myAlignAgain = new HashSet();
   @NotNull
   private final FormattingProgressCallback myProgressCallback;
-  
+
   private WhiteSpace                      myLastWhiteSpace;
   private boolean                         myDisposed;
   private CommonCodeStyleSettings.IndentOptions myJavaIndentOptions;
-  
+
   @NotNull
   private State myCurrentState;
 
@@ -164,10 +165,10 @@ class FormatProcessor {
                          CommonCodeStyleSettings.IndentOptions indentOptions,
                          @Nullable FormatTextRanges affectedRanges,
                          int interestingOffset,
-                         @NotNull FormattingProgressCallback progressCallback) 
+                         @NotNull FormattingProgressCallback progressCallback)
   {
     myProgressCallback = progressCallback;
-    myIndentOption = indentOptions;
+    myDefaultIndentOption = indentOptions;
     mySettings = settings;
     myDocument = docModel.getDocument();
     myCurrentState = new WrapBlocksState(rootBlock, docModel, affectedRanges, interestingOffset);
@@ -214,7 +215,7 @@ class FormatProcessor {
    * from EDT we have no chance of performing any other actions from EDT simultaneously (e.g. we may want to show progress bar
    * that reflects current formatting state but the progress bar can' bet updated if formatting is performed during a single long
    * method call). So, we can interleave formatting iterations with GUI state updates.
-   * 
+   *
    * @param model         target formatting model
    * @param sequentially  flag that indicates what kind of processing should be used
    */
@@ -232,9 +233,9 @@ class FormatProcessor {
 
   /**
    * Asks current processor to perform processing iteration
-   * 
+   *
    * @return    true if the processing is finished; false otherwise
-   * @see #format(FormattingModel, boolean) 
+   * @see #format(FormattingModel, boolean)
    */
   public boolean iteration() {
     if (myCurrentState.isDone()) {
@@ -250,19 +251,19 @@ class FormatProcessor {
   public void stopSequentialProcessing() {
     myCurrentState.stop();
   }
-  
+
   public void formatWithoutRealModifications() {
     formatWithoutRealModifications(false);
   }
-  
+
   @SuppressWarnings({"WhileLoopSpinsOnField"})
   public void formatWithoutRealModifications(boolean sequentially) {
     myCurrentState.setNext(new AdjustWhiteSpacesState());
-    
+
     if (sequentially) {
       return;
     }
-    
+
     doIterationsSynchronously(FormattingStateId.PROCESSING_BLOCKS);
   }
 
@@ -279,11 +280,11 @@ class FormatProcessor {
   public void performModifications(FormattingModel model) {
     performModifications(model, false);
   }
-  
+
   public void performModifications(FormattingModel model, boolean sequentially) {
     assert !myDisposed;
     myCurrentState.setNext(new ApplyChangesState(model));
-    
+
     if (sequentially) {
       return;
     }
@@ -292,9 +293,9 @@ class FormatProcessor {
   }
 
   /**
-   * Perform iterations against the {@link #myCurrentState current state} until it's {@link FormattingStateId type} 
+   * Perform iterations against the {@link #myCurrentState current state} until it's {@link FormattingStateId type}
    * is {@link FormattingStateId#getPreviousStates() less} or equal to the given state.
-   * 
+   *
    * @param state   target state to process
    */
   private void doIterationsSynchronously(@NotNull FormattingStateId state) {
@@ -304,7 +305,7 @@ class FormatProcessor {
       myCurrentState.iteration();
     }
   }
-  
+
   public void setJavaIndentOptions(final CommonCodeStyleSettings.IndentOptions javaIndentOptions) {
     myJavaIndentOptions = javaIndentOptions;
   }
@@ -312,7 +313,7 @@ class FormatProcessor {
   /**
    * Decides whether applying formatter changes should be applied incrementally one-by-one or merge result should be
    * constructed locally and the whole document text should be replaced. Performs such single bulk change if necessary.
-   * 
+   *
    * @param blocksToModify        changes introduced by formatter
    * @param model                 current formatting model
    * @param indentOption          indent options to use
@@ -320,8 +321,8 @@ class FormatProcessor {
    *                              false otherwise
    */
   @SuppressWarnings({"deprecation"})
-  private static boolean applyChangesAtBulkMode(final List blocksToModify, final FormattingModel model,
-                                                CommonCodeStyleSettings.IndentOptions indentOption)
+  private boolean applyChangesAtBulkMode(final List blocksToModify, final FormattingModel model,
+                                         @NotNull CommonCodeStyleSettings.IndentOptions indentOption)
   {
     FormattingDocumentModel documentModel = model.getDocumentModel();
     Document document = documentModel.getDocument();
@@ -335,7 +336,8 @@ class FormatProcessor {
     for (LeafBlockWrapper block : blocksToModify) {
       WhiteSpace whiteSpace = block.getWhiteSpace();
       CharSequence newWs = documentModel.adjustWhiteSpaceIfNecessary(
-        whiteSpace.generateWhiteSpace(indentOption), whiteSpace.getStartOffset(), whiteSpace.getEndOffset(), false
+        whiteSpace.generateWhiteSpace(getIndentOptionsToUse(block, indentOption)), whiteSpace.getStartOffset(),
+        whiteSpace.getEndOffset(), false
       );
       if (changes.size() > 10000) {
         CharSequence mergeResult = BulkChangesMerger.INSTANCE.mergeToCharSequence(document.getChars(), document.getTextLength(), changes);
@@ -361,7 +363,7 @@ class FormatProcessor {
     }
     blocks.clear();
   }
-  
+
   @Nullable
   private static DocumentEx getAffectedDocument(final FormattingModel model) {
     if (model instanceof DocumentBasedFormattingModel) {
@@ -408,7 +410,7 @@ class FormatProcessor {
     for (LeafBlockWrapper block = myFirstTokenBlock; block != null; block = block.getNextBlock()) {
       final WhiteSpace whiteSpace = block.getWhiteSpace();
       if (!whiteSpace.isReadOnly()) {
-        final String newWhiteSpace = whiteSpace.generateWhiteSpace(myIndentOption);
+        final String newWhiteSpace = whiteSpace.generateWhiteSpace(getIndentOptionsToUse(block, myDefaultIndentOption));
         if (!whiteSpace.equalsToString(newWhiteSpace)) {
           blocksToModify.add(block);
         }
@@ -417,6 +419,22 @@ class FormatProcessor {
     return blocksToModify;
   }
 
+  @NotNull
+  private CommonCodeStyleSettings.IndentOptions getIndentOptionsToUse(@NotNull AbstractBlockWrapper block,
+                                                                      @NotNull CommonCodeStyleSettings.IndentOptions fallbackIndentOptions)
+  {
+    final Language language = block.getLanguage();
+    if (language == null) {
+      return fallbackIndentOptions;
+    }
+    final CommonCodeStyleSettings commonSettings = mySettings.getCommonSettings(language);
+    if (commonSettings == null) {
+      return fallbackIndentOptions;
+    }
+    final CommonCodeStyleSettings.IndentOptions result = commonSettings.getIndentOptions();
+    return result == null ? fallbackIndentOptions : result;
+  }
+
   private static TextRange shiftRange(final TextRange textRange, final int shift) {
     return new TextRange(textRange.getStartOffset() + shift, textRange.getEndOffset() + shift);
   }
@@ -593,8 +611,8 @@ class FormatProcessor {
 
   private boolean isCandidateToBeWrapped(final WrapImpl wrap) {
     return isSuitableInTheCurrentPosition(wrap) &&
-      (wrap.getType() == WrapImpl.Type.WRAP_AS_NEEDED || wrap.getType() == WrapImpl.Type.CHOP_IF_NEEDED) &&
-      !myCurrentBlock.getWhiteSpace().isReadOnly();
+           (wrap.getType() == WrapImpl.Type.WRAP_AS_NEEDED || wrap.getType() == WrapImpl.Type.CHOP_IF_NEEDED) &&
+           !myCurrentBlock.getWhiteSpace().isReadOnly();
   }
 
   private void onCurrentLineChanged() {
@@ -627,9 +645,10 @@ class FormatProcessor {
       LOG.error(String.format("Can't find alignment processor for alignment anchor %s", alignment.getAnchor()));
       return true;
     }
-    
+
     BlockAlignmentProcessor.Context context = new BlockAlignmentProcessor.Context(
-      myDocument, alignment, myCurrentBlock, myAlignmentMappings, myBackwardShiftedAlignedBlocks, myIndentOption
+      myDocument, alignment, myCurrentBlock, myAlignmentMappings, myBackwardShiftedAlignedBlocks,
+      getIndentOptionsToUse(myCurrentBlock, myDefaultIndentOption)
     );
     BlockAlignmentProcessor.Result result = alignmentProcessor.applyAlignment(context);
     final LeafBlockWrapper offsetResponsibleBlock = alignment.getOffsetRespBlockBefore(myCurrentBlock);
@@ -704,7 +723,7 @@ class FormatProcessor {
   }
 
   private void adjustSpacingByIndentOffset() {
-    IndentData offset = myCurrentBlock.calculateOffset(myIndentOption);
+    IndentData offset = myCurrentBlock.calculateOffset(getIndentOptionsToUse(myCurrentBlock, myDefaultIndentOption));
     myCurrentBlock.getWhiteSpace().setSpaces(offset.getSpaces(), offset.getIndentSpaces());
   }
 
@@ -921,11 +940,11 @@ class FormatProcessor {
     ChildAttributesInfo info = getChildAttributesInfo(block, index, parent);
     if (info == null) {
       return new IndentInfo(0, 0, 0);
-    } 
+    }
 
     return adjustLineIndent(info.parent, info.attributes, info.index);
   }
-  
+
   @Nullable
   private static ChildAttributesInfo getChildAttributesInfo(@NotNull final Block block,
                                                             final int index,
@@ -972,7 +991,7 @@ class FormatProcessor {
   private IndentInfo adjustLineIndent(final AbstractBlockWrapper parent, final ChildAttributes childAttributes, final int index) {
     int alignOffset = getAlignOffsetBefore(childAttributes.getAlignment(), null);
     if (alignOffset == -1) {
-      return parent.calculateChildOffset(myIndentOption, childAttributes, index).createIndentInfo();
+      return parent.calculateChildOffset(getIndentOptionsToUse(parent, myDefaultIndentOption), childAttributes, index).createIndentInfo();
     }
     else {
       AbstractBlockWrapper indentedParentBlock = CoreFormatterUtil.getIndentedParentBlock(myCurrentBlock);
@@ -1062,8 +1081,8 @@ class FormatProcessor {
 
     if (current.getEndOffset() <= offset) {
       while (!current.isIncomplete() &&
-        current.getParent() != null &&
-        current.getParent().getEndOffset() <= offset) {
+             current.getParent() != null &&
+             current.getParent().getEndOffset() <= offset) {
         current = current.getParent();
       }
       if (current.isIncomplete()) return current;
@@ -1101,7 +1120,7 @@ class FormatProcessor {
   /**
    * There is a possible case that particular block is a composite block that contains number of nested composite blocks
    * that all target the same text range. This method allows to derive the most nested block that shares the same range (if any).
-   * 
+   *
    * @param block   block to check
    * @return        the most nested block of the given one that shares the same text range if any; given block otherwise
    */
@@ -1110,7 +1129,7 @@ class FormatProcessor {
     if (!(block instanceof CompositeBlockWrapper)) {
       return block;
     }
-    
+
     AbstractBlockWrapper result = block;
     AbstractBlockWrapper candidate = block;
     while (true) {
@@ -1180,11 +1199,11 @@ class FormatProcessor {
       }
     }
   }
-  
+
   private abstract class State {
 
     private final FormattingStateId myStateId;
-    
+
     private State   myNextState;
     private boolean myDone;
 
@@ -1221,10 +1240,10 @@ class FormatProcessor {
 
     public void stop() {
     }
-    
+
     protected abstract void doIteration();
     protected abstract void prepare();
-    
+
     private void shiftStateIfNecessary() {
       if (isDone() && myNextState != null) {
         myCurrentState = myNextState;
@@ -1233,7 +1252,7 @@ class FormatProcessor {
       }
     }
   }
-  
+
   private class WrapBlocksState extends State {
 
     private final InitialInfoBuilder      myWrapper;
@@ -1247,7 +1266,7 @@ class FormatProcessor {
       super(FormattingStateId.WRAPPING_BLOCKS);
       myModel = model;
       myWrapper = InitialInfoBuilder.prepareToBuildBlocksSequentially(
-        root, model, affectedRanges, myIndentOption, interestingOffset, myProgressCallback
+        root, model, affectedRanges, myDefaultIndentOption, interestingOffset, myProgressCallback
       );
     }
 
@@ -1260,7 +1279,7 @@ class FormatProcessor {
       if (isDone()) {
         return;
       }
-      
+
       setDone(myWrapper.iteration());
       if (!isDone()) {
         return;
@@ -1273,10 +1292,10 @@ class FormatProcessor {
       myCurrentBlock = myFirstTokenBlock;
       myTextRangeToWrapper = buildTextRangeToInfoMap(myFirstTokenBlock);
       myLastWhiteSpace = new WhiteSpace(getLastBlock().getEndOffset(), false);
-      myLastWhiteSpace.append(myModel.getTextLength(), myModel, myIndentOption);
+      myLastWhiteSpace.append(myModel.getTextLength(), myModel, myDefaultIndentOption);
     }
   }
-  
+
   private class AdjustWhiteSpacesState extends State {
 
     AdjustWhiteSpacesState() {
@@ -1294,11 +1313,11 @@ class FormatProcessor {
       if (blockToProcess != null) {
         myProgressCallback.afterProcessingBlock(blockToProcess);
       }
-      
+
       if (myCurrentBlock != null) {
         return;
       }
-      
+
       if (myAlignAgain.isEmpty()) {
         setDone(true);
       }
@@ -1309,7 +1328,7 @@ class FormatProcessor {
       }
     }
   }
-  
+
   private class ApplyChangesState extends State {
 
     private final FormattingModel        myModel;
@@ -1343,7 +1362,7 @@ class FormatProcessor {
         setDone(true);
         return;
       }
-      
+
       //for GeneralCodeFormatterTest
       if (myJavaIndentOptions == null) {
         myJavaIndentOptions = mySettings.getIndentOptions(StdFileTypes.JAVA);
@@ -1358,7 +1377,9 @@ class FormatProcessor {
         updatedDocument.setInBulkUpdate(true);
         myResetBulkUpdateState = true;
       }
-      if (blocksToModifyCount > BULK_REPLACE_OPTIMIZATION_CRITERIA && applyChangesAtBulkMode(myBlocksToModify, myModel, myIndentOption)) {
+      if (blocksToModifyCount > BULK_REPLACE_OPTIMIZATION_CRITERIA
+          && applyChangesAtBulkMode(myBlocksToModify, myModel, myDefaultIndentOption))
+      {
         setDone(true);
       }
     }
@@ -1367,7 +1388,11 @@ class FormatProcessor {
     protected void doIteration() {
       LeafBlockWrapper blockWrapper = myBlocksToModify.get(myIndex);
       myShift = replaceWhiteSpace(
-        myModel, blockWrapper, myShift, blockWrapper.getWhiteSpace().generateWhiteSpace(myIndentOption), myJavaIndentOptions
+        myModel,
+        blockWrapper,
+        myShift,
+        blockWrapper.getWhiteSpace().generateWhiteSpace(getIndentOptionsToUse(blockWrapper, myDefaultIndentOption)),
+        myJavaIndentOptions
       );
       myProgressCallback.afterApplyingChange(blockWrapper);
       // block could be gc'd
@@ -1375,7 +1400,7 @@ class FormatProcessor {
       blockWrapper.dispose();
       myBlocksToModify.set(myIndex, null);
       myIndex++;
-      
+
       if (myIndex >= myBlocksToModify.size()) {
         setDone(true);
       }
@@ -1384,7 +1409,7 @@ class FormatProcessor {
     @Override
     protected void setDone(boolean done) {
       super.setDone(done);
-      
+
       if (myResetBulkUpdateState) {
         DocumentEx document = getAffectedDocument(myModel);
         if (document != null) {
@@ -1392,7 +1417,7 @@ class FormatProcessor {
           myResetBulkUpdateState = false;
         }
       }
-      
+
       if (done) {
         myModel.commitChanges();
       }
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
index 0b47d69e55ef..afefeb6b6774 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
@@ -133,6 +133,7 @@ public class FormatterImpl extends FormatterEx
     return result;
   }
 
+  @NotNull
   public Spacing createSpacing(int minOffset,
                                int maxOffset,
                                int minLineFeeds,
@@ -141,13 +142,21 @@ public class FormatterImpl extends FormatterEx
     return getSpacingImpl(minOffset, maxOffset, minLineFeeds, false, false, keepLineBreaks, keepBlankLines,false, 0);
   }
 
+  @NotNull
   public Spacing getReadOnlySpacing() {
     return myReadOnlySpacing;
   }
-
-  public Spacing createDependentLFSpacing(int minOffset, int maxOffset, TextRange dependence, boolean keepLineBreaks,
-                                          int keepBlankLines) {
-    return new DependantSpacingImpl(minOffset, maxOffset, dependence, keepLineBreaks, keepBlankLines);
+  
+  @NotNull
+  @Override
+  public Spacing createDependentLFSpacing(int minSpaces,
+                                          int maxSpaces,
+                                          @NotNull TextRange dependencyRange,
+                                          boolean keepLineBreaks,
+                                          int keepBlankLines,
+                                          @NotNull DependentSpacingRule rule)
+  {
+    return new DependantSpacingImpl(minSpaces, maxSpaces, dependencyRange, keepLineBreaks, keepBlankLines, rule);
   }
 
   @NotNull
@@ -669,10 +678,12 @@ public class FormatterImpl extends FormatterEx
     return myAbsoluteLabelIndent;
   }
 
+  @NotNull
   public Spacing createSafeSpacing(final boolean shouldKeepLineBreaks, final int keepBlankLines) {
     return getSpacingImpl(0, 0, 0, false, true, shouldKeepLineBreaks, keepBlankLines, false, 0);
   }
 
+  @NotNull
   public Spacing createKeepingFirstColumnSpacing(final int minSpace,
                                                  final int maxSpace,
                                                  final boolean keepLineBreaks,
@@ -680,6 +691,7 @@ public class FormatterImpl extends FormatterEx
     return getSpacingImpl(minSpace, maxSpace, -1, false, false, keepLineBreaks, keepBlankLines, true, 0);
   }
 
+  @NotNull
   public Spacing createSpacing(final int minSpaces, final int maxSpaces, final int minLineFeeds, final boolean keepLineBreaks, final int keepBlankLines,
                                final int prefLineFeeds) {
     return getSpacingImpl(minSpaces, maxSpaces, -1, false, false, keepLineBreaks, keepBlankLines, false, prefLineFeeds);
diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java
index 1ee76f43d19a..7350201edbb8 100644
--- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java
+++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java
@@ -126,8 +126,8 @@ class InitialInfoBuilder {
                                          @Nullable final CompositeBlockWrapper parent,
                                          @Nullable WrapImpl currentWrapParent,
                                          @Nullable final Block parentBlock,
-                                         boolean rootBlockIsRightBlock
-  ) {
+                                         boolean rootBlockIsRightBlock)
+  {
     final WrapImpl wrap = (WrapImpl)rootBlock.getWrap();
     if (wrap != null) {
       wrap.registerParent(currentWrapParent);
diff --git a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java
index 108e089ab6cf..e721405fa300 100644
--- a/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java
+++ b/platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2012 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.
@@ -17,7 +17,9 @@ package com.intellij.formatting.templateLanguages;
 
 import com.intellij.formatting.*;
 import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
 import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.formatter.common.AbstractBlock;
 import com.intellij.psi.templateLanguages.OuterLanguageElement;
 import org.jetbrains.annotations.NotNull;
@@ -31,9 +33,10 @@ import java.util.List;
  *         Date: Jun 30, 2009
  *         Time: 7:18:37 PM
  */
-public class DataLanguageBlockWrapper implements ASTBlock, BlockWithParent {
+public class DataLanguageBlockWrapper implements ASTBlock, BlockEx, BlockWithParent {
   private final Block myOriginal;
   private final Indent myIndent;
+  @Nullable private final Language myLanguage;
   private List myBlocks;
   private List myTlBlocks;
   private BlockWithParent myParent;
@@ -44,8 +47,18 @@ public class DataLanguageBlockWrapper implements ASTBlock, BlockWithParent {
     assert !(original instanceof DataLanguageBlockWrapper) && !(original instanceof TemplateLanguageBlock);
     myOriginal = original;
     myIndent = indent;
-  }
 
+    final ASTNode node = getNode();
+    Language language = null;
+    if (node != null) {
+      final PsiElement psi = node.getPsi();
+      if (psi != null) {
+        language = psi.getLanguage();
+      }
+    }
+    myLanguage = language;
+  }
+  
   @NotNull
   public TextRange getTextRange() {
     return myOriginal.getTextRange();
@@ -59,6 +72,13 @@ public class DataLanguageBlockWrapper implements ASTBlock, BlockWithParent {
     return myBlocks;
   }
 
+  @Nullable
+  @Override
+  public Language getLanguage() {
+    // Use base language code style settings for the template blocks.
+    return myLanguage;
+  }
+
   private List buildBlocks() {
     assert myBlocks == null;
     if (isLeaf()) {
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/nodes/TodoFileNode.java b/platform/lang-impl/src/com/intellij/ide/todo/nodes/TodoFileNode.java
index 6a629737c801..1c16566a1fd0 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/nodes/TodoFileNode.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/nodes/TodoFileNode.java
@@ -31,7 +31,7 @@ import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.search.TodoItemImpl;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
 import com.intellij.psi.search.PsiTodoSearchHelper;
 import com.intellij.psi.search.TodoItem;
 import com.intellij.ui.HighlightedRegion;
@@ -102,7 +102,7 @@ public final class TodoFileNode extends PsiFileNode implements HighlightedRegion
       @Override
       public void visitElement(PsiElement element) {
         if (element instanceof PsiLanguageInjectionHost) {
-          InjectedLanguageFacadeImpl.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
+          InjectedLanguageUtil.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
             @Override
             public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) {
               if (places.size() == 1) {
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
index ff69f00bccb2..46341c274783 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
@@ -43,7 +43,7 @@ import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.UserDataHolderBase;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
 import com.intellij.util.containers.WeakList;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -113,7 +113,7 @@ public class EditorWindow extends UserDataHolderBase implements EditorEx {
       if (!editorWindow.isValid()) {
         editorWindow.dispose();
 
-        InjectedLanguageFacadeImpl.clearCaches(editorWindow.myInjectedFile, editorWindow.getDocument());
+        InjectedLanguageUtil.clearCaches(editorWindow.myInjectedFile, editorWindow.getDocument());
         iterator.remove();
       }
     }
diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java
index 0556784022bc..ee7a882a21a3 100644
--- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java
+++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java
@@ -23,7 +23,7 @@ import com.intellij.formatting.ASTBlock;
 import com.intellij.formatting.Block;
 import com.intellij.formatting.FormattingModel;
 import com.intellij.formatting.FormattingModelBuilder;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
 import com.intellij.ui.ListCellRendererWrapper;
 import com.intellij.ide.util.treeView.AbstractTreeStructure;
 import com.intellij.ide.util.treeView.NodeRenderer;
@@ -821,7 +821,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp
     }
     if (currentElem == null) {
       currentElem =
-        InjectedLanguageFacadeImpl
+        InjectedLanguageUtil
           .findElementAtNoCommit(psiEl.getContainingFile(), rootBlockNode.getBlock().getTextRange().getStartOffset());
     }
     myPsiToBlockMap.put(currentElem, rootBlockNode);
@@ -980,7 +980,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp
       BlockTreeNode descriptor = (BlockTreeNode)blockElementsSet.iterator().next();
       PsiElement rootPsi = ((ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure()).getRootPsiElement();
       int blockStart = descriptor.getBlock().getTextRange().getStartOffset();
-      PsiElement currentPsiEl = InjectedLanguageFacadeImpl.findElementAtNoCommit(rootPsi.getContainingFile(), blockStart);
+      PsiElement currentPsiEl = InjectedLanguageUtil.findElementAtNoCommit(rootPsi.getContainingFile(), blockStart);
       int blockLength = descriptor.getBlock().getTextRange().getLength();
       while (currentPsiEl.getParent() != null &&
              currentPsiEl.getTextRange().getStartOffset() == blockStart &&
@@ -1237,7 +1237,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp
       final PsiElement rootElement = ((ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure()).getRootPsiElement();
       int baseOffset = rootPsiElement.getTextRange().getStartOffset();
       final int offset = myEditor.getCaretModel().getOffset() + baseOffset;
-      final PsiElement element = InjectedLanguageFacadeImpl.findElementAtNoCommit(rootElement.getContainingFile(), offset);
+      final PsiElement element = InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), offset);
       if (element != null && myBlockTreeBuilder != null) {
         TextRange rangeInHostFile = InjectedLanguageManager.getInstance(myProject).injectedToHost(element, element.getTextRange());
         selectBlockNode(findBlockNode(rangeInHostFile, true));
@@ -1258,8 +1258,8 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp
       final int start = selection.getSelectionStart()+baseOffset;
       final int end = selection.getSelectionEnd()+baseOffset - 1;
       final PsiElement element =
-        findCommonParent(InjectedLanguageFacadeImpl.findElementAtNoCommit(rootElement.getContainingFile(), start),
-                         InjectedLanguageFacadeImpl.findElementAtNoCommit(rootElement.getContainingFile(), end));
+        findCommonParent(InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), start),
+                         InjectedLanguageUtil.findElementAtNoCommit(rootElement.getContainingFile(), end));
       if (element != null  && myBlockTreeBuilder != null) {
         if (myEditor.getContentComponent().hasFocus()) {
           TextRange rangeInHostFile = InjectedLanguageManager.getInstance(myProject).injectedToHost(element, element.getTextRange());
diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/ViewerTreeStructure.java b/platform/lang-impl/src/com/intellij/internal/psiView/ViewerTreeStructure.java
index 3f037ebdece6..48f1e2d4c506 100644
--- a/platform/lang-impl/src/com/intellij/internal/psiView/ViewerTreeStructure.java
+++ b/platform/lang-impl/src/com/intellij/internal/psiView/ViewerTreeStructure.java
@@ -29,7 +29,7 @@ import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.ArrayUtil;
 import org.jetbrains.annotations.NotNull;
@@ -99,7 +99,7 @@ public class ViewerTreeStructure extends AbstractTreeStructure {
             }
             final PsiElement psi = root.getPsi();
             if (psi instanceof PsiLanguageInjectionHost) {
-              InjectedLanguageFacadeImpl.enumerate(psi, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
+              InjectedLanguageUtil.enumerate(psi, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
                 @Override
                 public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) {
                   list.add(new Inject(psi, injectedPsi));
diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java
new file mode 100644
index 000000000000..9a45520091ef
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2012 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.lang.customFolding;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+
+/**
+ * @author Rustam Vishnyakov
+ */
+public class GotoCustomRegionAction extends AnAction implements DumbAware {
+  @Override
+  public void actionPerformed(AnActionEvent e) {
+    final Project project = e.getProject();
+    final Editor editor = e.getData(PlatformDataKeys.EDITOR);
+    if (Boolean.TRUE.equals(e.getData(PlatformDataKeys.IS_MODAL_CONTEXT))) {
+      return;
+    }
+    if (project != null && editor != null) {
+      if (DumbService.getInstance(project).isDumb()) {
+        DumbService.getInstance(project).showDumbModeNotification(IdeBundle.message("goto.custom.region.message.dumb.mode"));
+        return;
+      }
+      CommandProcessor processor = CommandProcessor.getInstance();
+      processor.executeCommand(
+        project,
+        new Runnable() {
+          public void run() {
+            GotoCustomRegionDialog dialog = new GotoCustomRegionDialog(project, editor);
+            dialog.show();
+            if (dialog.isOK()) {
+              PsiElement navigationElement = dialog.getNavigationElement();
+              if (navigationElement != null) {
+                navigateTo(editor, navigationElement);
+                IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation();
+              }
+            }
+          }
+        },
+        IdeBundle.message("goto.custom.region.command"),
+        null);
+    }
+  }
+
+  @Override
+  public void update(AnActionEvent e) {
+    Presentation presentation = e.getPresentation();
+    presentation.setText("Custom Region...");
+    final Editor editor = e.getData(PlatformDataKeys.EDITOR);
+    final Project project = e.getProject();
+    boolean isAvailable = editor != null && project != null;
+    presentation.setEnabled(isAvailable);
+    presentation.setVisible(isAvailable);
+  }
+
+  private static void navigateTo(Editor editor, PsiElement element) {
+    int offset = element.getTextRange().getStartOffset();
+    if (offset >= 0 && offset < editor.getDocument().getTextLength()) {
+      editor.getCaretModel().moveToOffset(offset);
+      editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
+      editor.getSelectionModel().removeSelection();
+    }
+  }
+}
diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.form b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.form
new file mode 100644
index 000000000000..cf1369bd01a7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.form
@@ -0,0 +1,25 @@
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.java b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.java new file mode 100644 index 000000000000..8873074402e3 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.java @@ -0,0 +1,169 @@ +/* + * Copyright 2000-2012 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.lang.customFolding; + +import com.intellij.ide.IdeBundle; +import com.intellij.lang.Language; +import com.intellij.lang.folding.*; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.ui.components.JBList; +import com.intellij.ui.components.JBScrollPane; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * @author Rustam Vishnyakov + */ +public class GotoCustomRegionDialog extends DialogWrapper { + private JBList myRegionsList; + private JPanel myContentPane; + private JBScrollPane myScrollPane; + private final Editor myEditor; + private final Project myProject; + + protected GotoCustomRegionDialog(@Nullable Project project, @NotNull Editor editor) { + super(project); + myEditor = editor; + myProject = project; + Collection descriptors = getCustomFoldingDescriptors(); + init(); + if (descriptors.size() == 0) { + myScrollPane.setVisible(false); + myContentPane.add(new JLabel(IdeBundle.message("goto.custom.region.message.unavailable")), BorderLayout.NORTH); + setOKActionEnabled(false); + } + else { + myRegionsList.setModel(new MyListModel(orderByPosition(descriptors))); + myRegionsList.setSelectedIndex(0); + } + setTitle(IdeBundle.message("goto.custom.region.command")); + } + + @Override + public JComponent getPreferredFocusedComponent() { + if (!myRegionsList.isEmpty()) { + return myRegionsList; + } + return super.getPreferredFocusedComponent(); + } + + @Override + protected JComponent createCenterPanel() { + return myContentPane; + } + + private Collection getCustomFoldingDescriptors() { + Set foldingDescriptors = new HashSet(); + final Document document = myEditor.getDocument(); + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); + PsiFile file = documentManager != null ? documentManager.getPsiFile(document) : null; + if (file != null) { + final FileViewProvider viewProvider = file.getViewProvider(); + for (final Language language : viewProvider.getLanguages()) { + final PsiFile psi = viewProvider.getPsi(language); + final FoldingBuilder foldingBuilder = LanguageFolding.INSTANCE.forLanguage(language); + if (psi != null) { + for (FoldingDescriptor descriptor : LanguageFolding.buildFoldingDescriptors(foldingBuilder, psi, document, false)) { + CustomFoldingBuilder customFoldingBuilder = getCustomFoldingBuilder(foldingBuilder, descriptor); + if (customFoldingBuilder != null) { + if (customFoldingBuilder.isCustomRegionStart(descriptor.getElement())) { + foldingDescriptors.add(descriptor); + } + } + } + } + } + } + return foldingDescriptors; + } + + private static Collection orderByPosition(Collection descriptors) { + List sorted = new ArrayList(descriptors.size()); + sorted.addAll(descriptors); + Collections.sort(sorted, new Comparator() { + @Override + public int compare(FoldingDescriptor descriptor1, FoldingDescriptor descriptor2) { + int pos1 = descriptor1.getElement().getTextRange().getStartOffset(); + int pos2 = descriptor2.getElement().getTextRange().getStartOffset(); + return pos1 - pos2; + } + }); + return sorted; + } + + private void createUIComponents() { + myRegionsList = new JBList(); + myRegionsList.setPreferredSize(new Dimension(200, 100)); + } + + @Nullable + private static CustomFoldingBuilder getCustomFoldingBuilder(FoldingBuilder builder, FoldingDescriptor descriptor) { + if (builder instanceof CustomFoldingBuilder) return (CustomFoldingBuilder)builder; + FoldingBuilder originalBuilder = descriptor.getElement().getUserData(CompositeFoldingBuilder.FOLDING_BUILDER); + if (originalBuilder instanceof CustomFoldingBuilder) return (CustomFoldingBuilder)originalBuilder; + return null; + } + + + private static class MyListModel extends DefaultListModel { + private MyListModel(Collection descriptors) { + for (FoldingDescriptor descriptor : descriptors) { + super.addElement(new MyFoldingDescriptorWrapper(descriptor)); + } + } + } + + private static class MyFoldingDescriptorWrapper { + private final @NotNull FoldingDescriptor myDescriptor; + + private MyFoldingDescriptorWrapper(@NotNull FoldingDescriptor descriptor) { + myDescriptor = descriptor; + } + + @NotNull + public FoldingDescriptor getDescriptor() { + return myDescriptor; + } + + @Nullable + @Override + public String toString() { + return myDescriptor.getPlaceholderText(); + } + } + + @Nullable + public PsiElement getNavigationElement() { + Object selection = myRegionsList.getSelectedValue(); + if (selection instanceof MyFoldingDescriptorWrapper) { + return ((MyFoldingDescriptorWrapper)selection).getDescriptor().getElement().getPsi(); + } + return null; + } +} diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java index e35ddf938039..d5761461754b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java @@ -27,7 +27,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.WolfTheProblemSolver; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.ui.ColorUtil; import com.intellij.ui.docking.DockManager; import org.jetbrains.annotations.NotNull; @@ -99,7 +99,7 @@ public class PsiAwareFileEditorManagerImpl extends FileEditorManagerImpl { return editor; } - return InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(editor, psiFile); + return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, psiFile); } /** diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java index ef799405eea6..0238e016a128 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java @@ -28,7 +28,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilBase; import org.jetbrains.annotations.Nullable; @@ -48,7 +48,7 @@ public class TextEditorPsiDataProvider implements EditorDataProvider { return e; } else { - return InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(e, getPsiFile(e, file)); + return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(e, getPsiFile(e, file)); } } if (dataId.equals(injectedId(PSI_ELEMENT.getName()))) { diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java index 1fe19548c3e9..e7885e247551 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java @@ -285,7 +285,7 @@ public class ModuleImpl extends ComponentManagerImpl implements ModuleEx { @SuppressWarnings({"HardCodedStringLiteral"}) public String toString() { if (myName == null) return "Module (not initialized)"; - return "Module: '" + getName() + "' " +(isDisposed() ? "(Disposed)" : "path: '" + getModuleFilePath() + "'"); + return "Module: '" + getName(); } private static String moduleNameByFileName(@NotNull String fileName) { diff --git a/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java b/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java index c6a15535bc30..7928ae5c37e8 100644 --- a/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/paths/StaticPathReferenceProvider.java @@ -20,10 +20,10 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -64,7 +64,7 @@ public class StaticPathReferenceProvider extends PathReferenceProviderBase { @Nullable public PathReference getPathReference(@NotNull final String path, @NotNull final PsiElement element) { - final ArrayList list = new ArrayList(5); + final List list = new SmartList(); createReferences(element, list, true); if (list.isEmpty()) return null; diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java index c0ab0725a6c1..c177b80b5dee 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java @@ -28,7 +28,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.PsiDocumentManagerImpl; import com.intellij.psi.impl.PsiToDocumentSynchronizer; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -128,7 +128,7 @@ public class FormattingDocumentModelImpl implements FormattingDocumentModel { if (strategy.check(myDocument.getCharsSequence(), startOffset, endOffset) >= endOffset) { return true; } - PsiElement injectedElement = myFile != null ? InjectedLanguageFacadeImpl.findElementAtNoCommit(myFile, startOffset) : null; + PsiElement injectedElement = myFile != null ? InjectedLanguageUtil.findElementAtNoCommit(myFile, startOffset) : null; if (injectedElement != null) { Language injectedLanguage = injectedElement.getLanguage(); if (!injectedLanguage.equals(myFile.getLanguage())) { diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/PsiBasedFormattingModel.java b/platform/lang-impl/src/com/intellij/psi/formatter/PsiBasedFormattingModel.java index 68bcf08c59ba..5fb63836e61d 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/PsiBasedFormattingModel.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/PsiBasedFormattingModel.java @@ -28,7 +28,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.TokenType; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.impl.source.SourceTreeToPsiMap; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -117,7 +117,7 @@ public class PsiBasedFormattingModel implements FormattingModel { Project project = containingFile.getProject(); assert !PsiDocumentManager.getInstance(project).isUncommited(myDocumentModel.getDocument()); // TODO:default project can not be used for injections, because latter might wants (unavailable) indices - PsiElement psiElement = project.isDefault() ? null : InjectedLanguageFacadeImpl.findInjectedElementNoCommit(containingFile, offset); + PsiElement psiElement = project.isDefault() ? null : InjectedLanguageUtil.findInjectedElementNoCommit(containingFile, offset); if (psiElement == null) psiElement = containingFile.findElementAt(offset); if (psiElement == null) return null; return psiElement.getNode(); diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java b/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java index 4d06bdc3b8e5..7070493c72a1 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java @@ -27,7 +27,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -76,7 +76,7 @@ public abstract class InjectedLanguageBlockBuilder { } } }; - InjectedLanguageFacadeImpl.enumerate(injectionHost.getPsi(), injectedPsiVisitor); + InjectedLanguageUtil.enumerate(injectionHost.getPsi(), injectedPsiVisitor); if (injectedFile[0] != null) { final Language childLanguage = injectedFile[0].getLanguage(); diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockWrapper.java b/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockWrapper.java index 717973a5c62c..38b968f912f6 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -132,7 +132,7 @@ public final class InjectedLanguageBlockWrapper implements Block { DependantSpacingImpl hostSpacing = (DependantSpacingImpl)spacing; return new DependantSpacingImpl( hostSpacing.getMinSpaces(), hostSpacing.getMaxSpaces(), hostSpacing.getDependency().shiftRight(shift), - hostSpacing.shouldKeepLineFeeds(), hostSpacing.getKeepBlankLines() + hostSpacing.shouldKeepLineFeeds(), hostSpacing.getKeepBlankLines(), DependentSpacingRule.DEFAULT ); } return spacing; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java index e251006a5428..f4a0db2a0ab2 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java @@ -25,7 +25,7 @@ import com.intellij.openapi.util.Segment; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -86,7 +86,7 @@ class InjectedSelfElementInfo extends SelfElementInfo { PsiDocumentManager documentManager = PsiDocumentManager.getInstance(hostFile.getProject()); Document document = documentManager.getDocument(hostFile); if (document != null && documentManager.isUncommited(document)) { - for (DocumentWindow documentWindow : InjectedLanguageFacadeImpl.getCachedInjectedDocuments(hostFile)) { + for (DocumentWindow documentWindow : InjectedLanguageUtil.getCachedInjectedDocuments(hostFile)) { PsiFile injected = documentManager.getPsiFile(documentWindow); if (injected != null) { visitor.visit(injected, Collections.emptyList()); @@ -94,7 +94,7 @@ class InjectedSelfElementInfo extends SelfElementInfo { } } else { - InjectedLanguageFacadeImpl.enumerate(hostContext, hostFile, true, visitor); + InjectedLanguageUtil.enumerate(hostContext, hostFile, true, visitor); } return result.get(); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java index 29442fd80cdf..fb8722d0156b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java @@ -29,7 +29,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.ProperTextRange; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.reference.SoftReference; import com.intellij.util.containers.UnsafeWeakList; import org.jetbrains.annotations.NotNull; @@ -72,7 +72,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager { } } - for (DocumentWindow injectedDoc : InjectedLanguageFacadeImpl.getCachedInjectedDocuments(file)) { + for (DocumentWindow injectedDoc : InjectedLanguageUtil.getCachedInjectedDocuments(file)) { PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc); if (injectedFile == null) continue; RangeMarker cachedMarker = getCachedRangeMarkerToInjectedFragment(injectedFile); @@ -114,7 +114,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager { } } - for (DocumentWindow injectedDoc : InjectedLanguageFacadeImpl.getCachedInjectedDocuments(file)) { + for (DocumentWindow injectedDoc : InjectedLanguageUtil.getCachedInjectedDocuments(file)) { PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc); if (injectedFile == null) continue; unfastenBelts(injectedFile, 0); @@ -145,7 +145,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager { } final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(file.getProject()); - for (Document document : InjectedLanguageFacadeImpl.getCachedInjectedDocuments(file)) { + for (Document document : InjectedLanguageUtil.getCachedInjectedDocuments(file)) { PsiFile injectedfile = psiDocumentManager.getPsiFile(document); if (injectedfile == null) continue; _synchronizePointers(injectedfile); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java index 1f87406009a6..42b4ee1f167b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java @@ -45,7 +45,7 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.codeStyle.CodeFormatterFacade; import com.intellij.psi.impl.source.codeStyle.IndentHelperImpl; import com.intellij.psi.impl.source.tree.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.LocalTimeCounter; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.TestOnly; @@ -168,7 +168,7 @@ public class PostprocessReformattingAspect implements PomModelAspect { if (changeSet == null) return; final PsiElement psiElement = changeSet.getRootElement().getPsi(); if (psiElement == null) return; - PsiFile containingFile = InjectedLanguageFacadeImpl.getTopLevelFile(psiElement); + PsiFile containingFile = InjectedLanguageUtil.getTopLevelFile(psiElement); final FileViewProvider viewProvider = containingFile.getViewProvider(); if (!viewProvider.isEventSystemEnabled()) return; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java index f6be88df1c35..d9af7a4b628a 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java @@ -45,7 +45,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.DocumentBasedFormattingModel; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.SourceTreeToPsiMap; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.testFramework.LightVirtualFile; @@ -88,7 +88,7 @@ public class CodeFormatterFacade { final Document document = file.getViewProvider().getDocument(); final RangeMarker rangeMarker = document != null && endOffset < document.getTextLength()? document.createRangeMarker(startOffset, endOffset):null; - PsiElement elementToFormat = document instanceof DocumentWindow ? InjectedLanguageFacadeImpl.getTopLevelFile(file) : psiElement; + PsiElement elementToFormat = document instanceof DocumentWindow ? InjectedLanguageUtil.getTopLevelFile(file) : psiElement; final PsiFile fileToFormat = elementToFormat.getContainingFile(); final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(fileToFormat); @@ -137,7 +137,7 @@ public class CodeFormatterFacade { Document document = PsiDocumentManager.getInstance(project).getDocument(file); final List textRanges = ranges.getRanges(); if (document instanceof DocumentWindow) { - file = InjectedLanguageFacadeImpl.getTopLevelFile(file); + file = InjectedLanguageUtil.getTopLevelFile(file); final DocumentWindow documentWindow = (DocumentWindow)document; for (FormatTextRanges.FormatTextRange range : textRanges) { range.setTextRange(documentWindow.injectedToHost(range.getTextRange())); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java index b6685b1e5e08..c0d69b38c25c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java @@ -38,7 +38,7 @@ import com.intellij.psi.impl.CheckUtil; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.CharTable; import com.intellij.util.IncorrectOperationException; @@ -274,7 +274,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager { TextRange textRange = addedElement.getTextRange(); final Document document = fileViewProvider.getDocument(); if (document instanceof DocumentWindow) { - containingFile = InjectedLanguageFacadeImpl.getTopLevelFile(containingFile); + containingFile = InjectedLanguageUtil.getTopLevelFile(containingFile); textRange = ((DocumentWindow)document).injectedToHost(textRange); } @@ -614,7 +614,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager { if (!(astNode instanceof FileElement)) { return new Pair(null, null); } - PsiElement elementAt = InjectedLanguageFacadeImpl.findInjectedElementNoCommit(file, offset); + PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(file, offset); final CharTable charTable = ((FileElement)astNode).getCharTable(); if (elementAt == null) { elementAt = findElementInTreeWithFormatterEnabled(file, offset); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java index 3862e08e4749..de0243002b23 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java @@ -28,7 +28,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.DocumentBasedFormattingModel; import com.intellij.psi.impl.source.SourceTreeToPsiMap; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.Nullable; @@ -56,7 +56,7 @@ abstract class CodeStyleManagerRunnable { Document document = documentManager.getDocument(file); if (document instanceof DocumentWindow) { final DocumentWindow documentWindow = (DocumentWindow)document; - final PsiFile topLevelFile = InjectedLanguageFacadeImpl.getTopLevelFile(file); + final PsiFile topLevelFile = InjectedLanguageUtil.getTopLevelFile(file); if (!file.equals(topLevelFile)) { if (range != null) { range = documentWindow.injectedToHost(range); @@ -125,7 +125,7 @@ abstract class CodeStyleManagerRunnable { return false; } - if (element instanceof PsiLanguageInjectionHost && InjectedLanguageFacadeImpl.hasInjections((PsiLanguageInjectionHost)element)) { + if (element instanceof PsiLanguageInjectionHost && InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost)element)) { return false; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java index b76d8c89d481..2d73b9b02f82 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java @@ -25,7 +25,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -306,7 +306,7 @@ public class FileReferenceSet { @Nullable private PsiFile getContainingFile() { - final PsiFile file = InjectedLanguageFacadeImpl.getTopLevelFile(myElement.getContainingFile()); + final PsiFile file = InjectedLanguageUtil.getTopLevelFile(myElement.getContainingFile()); if (file == null) { LOG.error("Invalid element: " + myElement); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java index 21b6a6a4841c..4cd558854598 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java @@ -90,7 +90,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme PsiFile hostFile = documentManager.getPsiFile(hostDocument); Language language = getBaseLanguage(); PsiFile file = getPsi(language); - final Language hostFileLanguage = InjectedLanguageFacadeImpl.getTopLevelFile(file).getLanguage(); + final Language hostFileLanguage = InjectedLanguageUtil.getTopLevelFile(file).getLanguage(); PsiFile hostPsiFileCopy = (PsiFile)hostFile.copy(); Segment firstTextRange = oldDocumentWindow.getHostRanges()[0]; PsiElement hostElementCopy = hostPsiFileCopy.getViewProvider().findElementAt(firstTextRange.getStartOffset(), hostFileLanguage); @@ -108,7 +108,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme for (PsiElement current = hostElementCopy; current != null && current != hostPsiFileCopy; current = current.getParent()) { current.putUserData(LANGUAGE_FOR_INJECTED_COPY_KEY, language); try { - InjectedLanguageFacadeImpl.enumerate(current, hostPsiFileCopy, false, visitor); + InjectedLanguageUtil.enumerate(current, hostPsiFileCopy, false, visitor); } finally { current.putUserData(LANGUAGE_FOR_INJECTED_COPY_KEY, null); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java index 8a086947820c..250bcbed8cd1 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java @@ -131,7 +131,7 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme if (hostPsiFile == null) return; final CopyOnWriteArrayList injected = - (CopyOnWriteArrayList)InjectedLanguageFacadeImpl.getCachedInjectedDocuments(hostPsiFile); + (CopyOnWriteArrayList)InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile); if (injected.isEmpty()) return; if (myProgress.isCanceled()) { @@ -157,7 +157,7 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme } final DocumentWindow[] stillInjectedDocument = {null}; // it is here where the reparse happens and old file contents replaced - InjectedLanguageFacadeImpl.enumerate(element, hostPsiFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() { + InjectedLanguageUtil.enumerate(element, hostPsiFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { stillInjectedDocument[0] = (DocumentWindow)injectedPsi.getViewProvider().getDocument(); @@ -333,7 +333,7 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme @SuppressWarnings({"ConstantConditions", "unchecked"}) @NotNull public List intersectWithAllEditableFragments(@NotNull PsiFile injectedPsi, @NotNull TextRange rangeToEdit) { - Place shreds = InjectedLanguageFacadeImpl.getShreds(injectedPsi); + Place shreds = InjectedLanguageUtil.getShreds(injectedPsi); if (shreds == null) return Collections.emptyList(); Object result = null; // optimization: TextRange or ArrayList int count = 0; @@ -381,12 +381,12 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme @Override public PsiElement findInjectedElementAt(@NotNull PsiFile hostFile, int hostDocumentOffset) { - return InjectedLanguageFacadeImpl.findInjectedElementNoCommit(hostFile, hostDocumentOffset); + return InjectedLanguageUtil.findInjectedElementNoCommit(hostFile, hostDocumentOffset); } @Override public void dropFileCaches(@NotNull PsiFile file) { - InjectedLanguageFacadeImpl.clearCachedInjectedFragmentsForFile(file); + InjectedLanguageUtil.clearCachedInjectedFragmentsForFile(file); } private final Map myInjectorsClone = new HashMap(); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageFacadeImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java similarity index 99% rename from platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageFacadeImpl.java rename to platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 4a019a46fac2..c0508eab7a08 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageFacadeImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -46,7 +46,7 @@ import java.util.List; /** * @author cdr */ -public class InjectedLanguageFacadeImpl extends InjectedLanguageFacade { +public class InjectedLanguageUtil extends InjectedLanguageFacade { static final Key, TextRange>>> HIGHLIGHT_TOKENS = Key.create("HIGHLIGHT_TOKENS"); public static void forceInjectionOnElement(@NotNull PsiElement host) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java index 19ca2be6c298..d1ee84f27989 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java @@ -256,7 +256,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT PsiFile newFile = registerDocument(documentWindow, psiFile, place, myHostPsiFile, documentManager); boolean mergeHappened = newFile != psiFile; if (mergeHappened) { - InjectedLanguageFacadeImpl.clearCaches(psiFile, documentWindow); + InjectedLanguageUtil.clearCaches(psiFile, documentWindow); psiFile = newFile; viewProvider = (InjectedFileViewProvider)psiFile.getViewProvider(); documentWindow = (DocumentWindowImpl)viewProvider.getDocument(); @@ -274,7 +274,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT try { List, TextRange>> tokens = obtainHighlightTokensFromLexer(myLanguage, outChars, escapers, place, virtualFile, myProject); - psiFile.putUserData(InjectedLanguageFacadeImpl.HIGHLIGHT_TOKENS, tokens); + psiFile.putUserData(InjectedLanguageUtil.HIGHLIGHT_TOKENS, tokens); } catch (ProcessCanceledException e) { throw e; @@ -385,7 +385,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT final Place shreds, final PsiFile hostPsiFile, final PsiDocumentManager documentManager) { - List injected = InjectedLanguageFacadeImpl.getCachedInjectedDocuments(hostPsiFile); + List injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile); for (int i = injected.size()-1; i>=0; i--) { DocumentWindowImpl oldDocument = (DocumentWindowImpl)injected.get(i); diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java b/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java index 47a07ed76341..ab7347afcf4b 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java @@ -19,6 +19,7 @@ */ package com.intellij.psi.stubs; +import com.intellij.util.indexing.IOUtils; import com.intellij.util.io.UnsyncByteArrayInputStream; import org.jetbrains.annotations.Nullable; @@ -38,15 +39,12 @@ public class SerializedStubTree { } public SerializedStubTree(DataInput in) throws IOException { - myLength = in.readInt(); - myBytes = new byte[myLength]; - myStubElement = null; - in.readFully(myBytes); + myBytes = IOUtils.readCompressed(in); + myLength = myBytes.length; } - public void write(DataOutput out) throws IOException{ - out.writeInt(myLength); - out.write(myBytes, 0, myLength); + public void write(DataOutput out) throws IOException { + IOUtils.writeCompressed(out, myBytes, myLength); } // willIndexStub is one time optimization hint, once can safely pass false diff --git a/platform/lang-impl/src/com/intellij/refactoring/move/FileReferenceContextUtil.java b/platform/lang-impl/src/com/intellij/refactoring/move/FileReferenceContextUtil.java index a15dfa42e4f2..0afa6b6545fc 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/move/FileReferenceContextUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/move/FileReferenceContextUtil.java @@ -22,7 +22,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceOwner; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; @@ -43,7 +43,7 @@ public class FileReferenceContextUtil { element.accept(new PsiRecursiveElementWalkingVisitor(true) { @Override public void visitElement(PsiElement element) { if (element instanceof PsiLanguageInjectionHost) { - InjectedLanguageFacadeImpl.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() { + InjectedLanguageUtil.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List places) { encodeFileReferences(injectedPsi); } @@ -89,7 +89,7 @@ public class FileReferenceContextUtil { } if (element instanceof PsiLanguageInjectionHost) { - InjectedLanguageFacadeImpl.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() { + InjectedLanguageUtil.enumerate(element, new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List places) { decodeFileReferences(injectedPsi); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java index 3b5c3f49bdfd..c23fe24e664d 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java @@ -31,7 +31,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Condition; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.meta.PsiMetaOwner; import com.intellij.psi.meta.PsiWritableMetaData; import com.intellij.refactoring.RefactoringBundle; @@ -57,7 +57,7 @@ public class PsiElementRenameHandler implements RenameHandler { public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { PsiElement element = getElement(dataContext); editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); - final PsiElement nameSuggestionContext = InjectedLanguageFacadeImpl.findElementAtNoCommit(file, editor.getCaretModel().getOffset()); + final PsiElement nameSuggestionContext = InjectedLanguageUtil.findElementAtNoCommit(file, editor.getCaretModel().getOffset()); invoke(element, project, nameSuggestionContext, editor); } @@ -127,7 +127,7 @@ public class PsiElementRenameHandler implements RenameHandler { } } - if (InjectedLanguageFacadeImpl.isInInjectedLanguagePrefixSuffix(element)) { + if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(element)) { final String message = RefactoringBundle.message("error.in.injected.lang.prefix.suffix", UsageViewUtil.getType(element)); return RefactoringBundle.getCannotRefactorMessage(message); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index 80542b6a3c6a..2a963e5ad5fa 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -62,7 +62,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.ProjectScope; import com.intellij.psi.search.PsiSearchHelper; @@ -151,7 +151,7 @@ public abstract class InplaceRefactoring { public boolean performInplaceRefactoring(final LinkedHashSet nameSuggestions) { myNameSuggestions = nameSuggestions; - if (InjectedLanguageFacadeImpl.isInInjectedLanguagePrefixSuffix(myElementToRename)) { + if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(myElementToRename)) { return false; } @@ -274,7 +274,7 @@ public abstract class InplaceRefactoring { } else { revertState(); - final TemplateState templateState = TemplateManagerImpl.getTemplateState(InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor)); + final TemplateState templateState = TemplateManagerImpl.getTemplateState(InjectedLanguageUtil.getTopLevelEditor(myEditor)); if (templateState != null) { templateState.gotoEnd(true); } @@ -332,7 +332,7 @@ public abstract class InplaceRefactoring { TextRange range = myScope.getTextRange(); assert range != null; myHighlighters = new ArrayList(); - Editor topLevelEditor = InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor); + Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor); topLevelEditor.getCaretModel().moveToOffset(range.getStartOffset()); TemplateManager.getInstance(myProject).startTemplate(topLevelEditor, template, templateListener); @@ -508,7 +508,7 @@ public abstract class InplaceRefactoring { if (myOldName == null) return; CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { public void run() { - final Editor topLevelEditor = InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor); + final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor); ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { final TemplateState state = TemplateManagerImpl.getTemplateState(topLevelEditor); @@ -751,7 +751,7 @@ public abstract class InplaceRefactoring { finally { if (!bind) { try { - ((EditorImpl)InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor)).stopDumb(); + ((EditorImpl)InjectedLanguageUtil.getTopLevelEditor(myEditor)).stopDumb(); } finally { FinishMarkAction.finish(myProject, myEditor, myMarkAction); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java index f6a107357ad9..45d74ff03420 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java @@ -28,7 +28,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiNameIdentifierOwner; import com.intellij.psi.PsiNamedElement; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.rename.RenamePsiElementProcessor; import org.jetbrains.annotations.NotNull; @@ -73,7 +73,7 @@ public class MemberInplaceRenameHandler extends VariableInplaceRenameHandler { else { final InplaceRefactoring inplaceRefactoring = editor.getUserData(InplaceRefactoring.INPLACE_RENAMER); if (inplaceRefactoring != null && inplaceRefactoring.getClass() == MemberInplaceRenamer.class) { - final TemplateState templateState = TemplateManagerImpl.getTemplateState(InjectedLanguageFacadeImpl.getTopLevelEditor(editor)); + final TemplateState templateState = TemplateManagerImpl.getTemplateState(InjectedLanguageUtil.getTopLevelEditor(editor)); if (templateState != null) { templateState.gotoEnd(true); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java index 062fc1aa8a65..caf14daadbf3 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java @@ -30,7 +30,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.ProjectScope; import com.intellij.psi.search.SearchScope; @@ -202,7 +202,7 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { } finally { try { - ((EditorImpl)InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor)).stopDumb(); + ((EditorImpl)InjectedLanguageUtil.getTopLevelEditor(myEditor)).stopDumb(); } finally { FinishMarkAction.finish(myProject, myEditor, markAction); @@ -248,7 +248,7 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { @Override protected void revertStateOnFinish() { - final Editor editor = InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor); + final Editor editor = InjectedLanguageUtil.getTopLevelEditor(myEditor); if (editor == FileEditorManager.getInstance(myProject).getSelectedTextEditor()) { ((EditorImpl)editor).startDumb(); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java index 70960742e739..7db3a3693faf 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MyLookupExpression.java @@ -30,7 +30,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.codeStyle.SuggestedNameInfo; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.refactoring.rename.NameSuggestionProvider; import com.intellij.refactoring.rename.PreferrableNameSuggestionProvider; @@ -78,7 +78,7 @@ public class MyLookupExpression extends Expression { @Override public void handleInsert(InsertionContext context, LookupElement item) { if (shouldSelectAll) return; - final Editor topLevelEditor = InjectedLanguageFacadeImpl.getTopLevelEditor(context.getEditor()); + final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(context.getEditor()); final TemplateState templateState = TemplateManagerImpl.getTemplateState(topLevelEditor); if (templateState != null) { final TextRange range = templateState.getCurrentVariableRange(); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index 222ca0db8098..f52e6635ef16 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -32,7 +32,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.rename.AutomaticRenamingDialog; @@ -249,7 +249,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring { } finally { try { - ((EditorImpl)InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor)).stopDumb(); + ((EditorImpl)InjectedLanguageUtil.getTopLevelEditor(myEditor)).stopDumb(); } finally { FinishMarkAction.finish(myProject, myEditor, markAction); @@ -298,7 +298,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring { revertStateOnFinish(); } else { - ((EditorImpl)InjectedLanguageFacadeImpl.getTopLevelEditor(myEditor)).stopDumb(); + ((EditorImpl)InjectedLanguageUtil.getTopLevelEditor(myEditor)).stopDumb(); } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IOUtils.java b/platform/lang-impl/src/com/intellij/util/indexing/IOUtils.java new file mode 100644 index 000000000000..b775f9fa4a13 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/indexing/IOUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2012 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.indexing; + +import com.intellij.util.io.DataInputOutputUtil; +import org.xerial.snappy.Snappy; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.lang.ref.SoftReference; +import java.lang.reflect.Field; + +/** + * @author Maxim.Mossienko + */ +public class IOUtils { + private static volatile boolean canUseSnappy; + static { + try { + Field impl = Snappy.class.getDeclaredField("impl"); + impl.setAccessible(true); + canUseSnappy = impl.get(null) != null && System.getProperty("idea.no.snappy") == null; + } + catch (Throwable e) {} + } + + private static final int COMPRESSION_THRESHOLD = 64; + private static final ThreadLocal> spareBufferLocal = new ThreadLocal>(); + + public static int writeCompressed(DataOutput out, byte[] bytes, int length) throws IOException { + if (length > COMPRESSION_THRESHOLD && canUseSnappy) { + SoftReference reference = spareBufferLocal.get(); + byte[] compressedOutputBuffer = reference != null ? reference.get():null; + int maxCompressedSize = 32 + length + length / 6; // snappy.cc#MaxCompressedLength + if (compressedOutputBuffer == null || compressedOutputBuffer.length < maxCompressedSize) { + compressedOutputBuffer = new byte[maxCompressedSize]; + spareBufferLocal.set(new SoftReference(compressedOutputBuffer)); + } + int compressedSize = Snappy.rawCompress(bytes, 0, length, compressedOutputBuffer, 0); + DataInputOutputUtil.writeINT(out, -compressedSize); + out.write(compressedOutputBuffer, 0, compressedSize); + return compressedSize; + } else { + DataInputOutputUtil.writeINT(out, length); + out.write(bytes, 0, length); + return length; + } + } + + public static final byte[] readCompressed(DataInput in) throws IOException { + int size = DataInputOutputUtil.readINT(in); + byte[] bytes = new byte[Math.abs(size)]; + in.readFully(bytes); + if (size >= 0) { + return bytes; + } else { + if (!canUseSnappy) throw new IOException("Can not read compressed data"); + return Snappy.uncompress(bytes); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java index 36ef41459f42..c7280faea5c1 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -85,7 +85,7 @@ class ValueContainerImpl extends UpdatableValueContainer implement final Value value = valueIterator.next(); if (isAssociated(value, inputId)) { if (toRemove == null) toRemove = new SmartList(); - else LOG.error("Expected only one value per-inputId"); + else LOG.error("Expected only one value per-inputId", String.valueOf(toRemove.get(0)), String.valueOf(value)); toRemove.add(value); } } diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java index f366cb5e69b5..b6fa20a49a20 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java @@ -67,7 +67,7 @@ public interface IdeActions { @NonNls String ACTION_SHOW_INTENTION_ACTIONS = "ShowIntentionActions"; @NonNls String ACTION_CODE_COMPLETION = "CodeCompletion"; @NonNls String ACTION_SMART_TYPE_COMPLETION = "SmartTypeCompletion"; - @NonNls String ACTION_CLASS_NAME_COMPLETION = "ClassNameCompletion"; + @Deprecated @NonNls String ACTION_CLASS_NAME_COMPLETION = "ClassNameCompletion"; @NonNls String ACTION_CHOOSE_LOOKUP_ITEM = "EditorChooseLookupItem"; @NonNls String ACTION_CHOOSE_LOOKUP_ITEM_ALWAYS = "EditorChooseLookupItemAlways"; @NonNls String ACTION_CHOOSE_LOOKUP_ITEM_REPLACE = "EditorChooseLookupItemReplace"; diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java b/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java index feb8f7752514..a5b9bf5ad80a 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java @@ -675,6 +675,9 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable { protected void processMouseEvent(MouseEvent e) { super.processMouseEvent(e); + if (!isShowing()) { + return; + } switch (e.getID()) { case MouseEvent.MOUSE_ENTERED: setCursor(getResizeCursor()); diff --git a/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java b/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java index 5423add1433a..ff9fc814f2f1 100644 --- a/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java +++ b/platform/platform-api/src/com/intellij/ui/speedSearch/ListWithFilter.java @@ -111,7 +111,7 @@ public class ListWithFilter extends JPanel implements DataProvider { private class MySpeedSearch extends SpeedSearch { boolean searchFieldShown = false; - protected void update() { + public void update() { mySpeedSearchPatternField.setBackground(new JTextField().getBackground()); onSpeedSearchPatternChanged(); mySpeedSearchPatternField.setText(getFilter()); diff --git a/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearch.java b/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearch.java index 1d3f237955e4..4749a4845a4c 100644 --- a/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearch.java +++ b/platform/platform-api/src/com/intellij/ui/speedSearch/SpeedSearch.java @@ -68,7 +68,7 @@ public class SpeedSearch { } } - protected void update() { + public void update() { } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java index e8d503e2f35d..17ff11cc8d1f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java @@ -474,7 +474,7 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern } myPluginsListUrl = DEFAULT_PLUGINS_HOST + "/plugins/list/"; - myPluginsDownloadUrl = DEFAULT_PLUGINS_HOST + "/pluginManager"; + myPluginsDownloadUrl = DEFAULT_PLUGINS_HOST + "/pluginManager/"; Element pluginsElement = parentNode.getChild(ELEMENT_PLUGINS); if (pluginsElement != null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/HungryBackspaceAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/HungryBackspaceAction.java new file mode 100644 index 000000000000..548b4ff95107 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/HungryBackspaceAction.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2012 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.openapi.editor.actions; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.editor.actionSystem.EditorActionManager; +import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.NotNull; + +/** + * Works like a usual backspace except the situation when the caret is located after white space - all white space symbols + * (white spaces, tabulations, line feeds) are removed then. + * + * @author Denis Zhdanov + * @since 6/27/12 4:10 PM + */ +public class HungryBackspaceAction extends TextComponentEditorAction { + + public HungryBackspaceAction() { + super(new Handler()); + } + + private static class Handler extends EditorWriteActionHandler { + @Override + public void executeWriteAction(@NotNull Editor editor, DataContext dataContext) { + final Document document = editor.getDocument(); + final int prevSymbolOffset = editor.getCaretModel().getOffset() - 1; + if (prevSymbolOffset < 0) { + return; + } + + final SelectionModel selectionModel = editor.getSelectionModel(); + final CharSequence text = document.getCharsSequence(); + final char c = text.charAt(prevSymbolOffset); + final boolean doHungryCheck = !selectionModel.hasSelection() && !selectionModel.hasBlockSelection() && StringUtil.isWhiteSpace(c); + final EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE); + handler.execute(editor, dataContext); + + if (!doHungryCheck) { + return; + } + + final int endOffset = prevSymbolOffset; + if (endOffset > document.getTextLength()) { + return; + } + int startOffset = CharArrayUtil.shiftBackward(text, endOffset - 1, "\t \n"); + if (startOffset < 0) { + // No non-white space symbol before the current caret offset has been found. + startOffset = 0; + } + else { + // Offset now points to the first non-white space symbol before the caret. + // Increment it to point to the first white space symbol instead. + startOffset++; + } + if (startOffset >= endOffset) { + return; + } + document.deleteString(startOffset, endOffset); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index c6a1c0747dac..c6f987bfe094 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1336,23 +1336,78 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return new Point(x, y); } - private int getTabbedTextWidth(int startOffset, int length, int xOffset) { + private int calcEndOffset(int startOffset, int visualColumn) { + FoldRegion[] regions = myFoldingModel.fetchTopLevel(); + if (regions == null) { + return startOffset + visualColumn; + } + + int low = 0; + int high = regions.length - 1; + int i = -1; + + while (low <= high) { + int mid = (low + high) >>> 1; + FoldRegion midVal = regions[mid]; + + if (midVal.getStartOffset() <= startOffset && midVal.getEndOffset() > startOffset) { + i = mid; + break; + } + + if (midVal.getStartOffset() < startOffset) + low = mid + 1; + else if (midVal.getStartOffset() > startOffset) + high = mid - 1; + } + if (i < 0) { + i = low; + } + + int result = startOffset; + int columnsToProcess = visualColumn; + for (; i < regions.length; i++) { + FoldRegion region = regions[i]; + + // Process text between the last fold region end and current fold region start. + int nonFoldTextColumnsNumber = region.getStartOffset() - result; + if (nonFoldTextColumnsNumber >= columnsToProcess) { + return result + columnsToProcess; + } + columnsToProcess -= nonFoldTextColumnsNumber; + + // Process fold region. + int placeHolderLength = region.getPlaceholderText().length(); + if (placeHolderLength >= columnsToProcess) { + return region.getEndOffset(); + } + result = region.getEndOffset(); + columnsToProcess -= placeHolderLength; + } + return result + columnsToProcess; + } + + private int getTabbedTextWidth(int startOffset, int targetColumn, int xOffset) { int x = xOffset; if (startOffset == 0 && myPrefixText != null) { x += myPrefixWidthInPixels; } - if (length <= 0) return x; + if (targetColumn <= 0) return x; int offset = startOffset; CharSequence text = myDocument.getCharsNoThreadCheck(); int textLength = myDocument.getTextLength(); - IterationState state = new IterationState(this, startOffset, startOffset + length, false); + + // We need to calculate max offset to provide to the IterationState here based on the given start offset and target + // visual column. The problem is there is a possible case that there is a collapsed fold region at the target interval, + // so, we can't just use 'startOffset + targetColumn' as a max end offset. + IterationState state = new IterationState(this, startOffset, calcEndOffset(startOffset, targetColumn), false); try { int fontType = state.getMergedAttributes().getFontType(); int spaceSize = EditorUtil.getSpaceWidth(fontType, this); int column = 0; outer: - while (column < length) { + while (column < targetColumn) { if (offset >= textLength) break; if (offset >= state.getEndOffset()) { @@ -1375,7 +1430,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi for (char aPlaceholder : placeholder) { x += EditorUtil.charWidth(aPlaceholder, fontType, this); column++; - if (column >= length) break outer; + if (column >= targetColumn) break outer; } offset = region.getEndOffset(); } @@ -1404,8 +1459,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } } - if (column != length) { - x += EditorUtil.getSpaceWidth(fontType, this) * (length - column); + if (column != targetColumn) { + x += EditorUtil.getSpaceWidth(fontType, this) * (targetColumn - column); } return x; diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java index 78cce1952c4f..978af235243e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java @@ -18,6 +18,7 @@ package com.intellij.openapi.updateSettings.impl; import com.intellij.ide.IdeBundle; import com.intellij.ide.plugins.*; import com.intellij.ide.startup.StartupActionScriptManager; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; @@ -374,10 +375,12 @@ public class PluginDownloader { } public static PluginDownloader createDownloader(IdeaPluginDescriptor pluginDescriptor) throws UnsupportedEncodingException { + String installationUUID = UpdateChecker.getInstallationUID(PropertiesComponent.getInstance()); + final BuildNumber buildNumber = ApplicationInfo.getInstance().getBuild(); @NonNls String url = RepositoryHelper.DOWNLOAD_URL + URLEncoder.encode(pluginDescriptor.getPluginId().getIdString(), "UTF8") + - "&build=" + buildNumber.asString(); + "&build=" + buildNumber.asString() + "&uuid=" + URLEncoder.encode(installationUUID, "UTF8"); if (pluginDescriptor instanceof PluginNode && ((PluginNode)pluginDescriptor).getDownloadUrl() != null){ url = ((PluginNode)pluginDescriptor).getDownloadUrl(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java index 139541d85171..007487984356 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java @@ -93,9 +93,10 @@ public class FileWatcher { private FileWatcher() { // to avoid deadlock (PY-1215), initialize ManagingFS reference in main thread, not in FileWatcher thread myManagingFS = ManagingFS.getInstance(); - + + final boolean explicitlyDisabled = Boolean.parseBoolean(System.getProperty(PROPERTY_WATCHER_DISABLED)); try { - if (!"true".equals(System.getProperty(PROPERTY_WATCHER_DISABLED))) { + if (!explicitlyDisabled) { startupProcess(false); } } @@ -117,8 +118,10 @@ public class FileWatcher { }, "FileWatcher shutdown hook")); } else { - LOG.info("Native file watcher failed to startup."); - notifyOnFailure("File watcher failed to startup", null); + String message = explicitlyDisabled ? String.format("File watcher is disabled ('%s' property is set)", PROPERTY_WATCHER_DISABLED) + : "File watcher failed to startup"; + LOG.info(message); + notifyOnFailure(message, null); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java index d8c59f6c95f4..2edbd3308861 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java @@ -51,7 +51,7 @@ import java.util.concurrent.ScheduledFuture; public class FSRecords implements Forceable { private static final Logger LOG = Logger.getInstance("#com.intellij.vfs.persistent.FSRecords"); - private static final int VERSION = 16; + private static final int VERSION = 17; private static final int PARENT_OFFSET = 0; private static final int PARENT_SIZE = 4; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java index 613a2f188726..c8365cf2b222 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java @@ -513,7 +513,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { // we should cache every local files content // because the local history feature is currently depends on this cache, // perforce offline mode as well - if ((!delegate.isReadOnly() || !application.isInternal() && !application.isUnitTestMode()) && + if ((!delegate.isReadOnly() || + // do not cache archive content unless asked + (cacheContent && !application.isInternal() && !application.isUnitTestMode())) && content.length <= PersistentFSConstants.FILE_LENGTH_TO_CACHE_THRESHOLD) { synchronized (INPUT_LOCK) { writeContent(canonicalFile, new ByteSequence(content), delegate.isReadOnly()); diff --git a/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java b/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java index bcac9e54ca38..16b6967f9e4f 100644 --- a/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java @@ -17,9 +17,11 @@ package com.intellij.psi.statistics.impl; import com.intellij.CommonBundle; import com.intellij.ide.IdeBundle; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Disposer; import com.intellij.psi.statistics.StatisticsInfo; import com.intellij.psi.statistics.StatisticsManager; import com.intellij.reference.SoftReference; @@ -43,6 +45,7 @@ public class StatisticsManagerImpl extends StatisticsManager { private final SoftReference[] myUnits = new SoftReference[UNIT_COUNT]; private final HashSet myModifiedUnits = new HashSet(); + private boolean myTestingStatistics; public int getUseCount(@NotNull final StatisticsInfo info) { if (info == StatisticsInfo.EMPTY) return 0; @@ -57,6 +60,9 @@ public class StatisticsManagerImpl extends StatisticsManager { public void incUseCount(@NotNull final StatisticsInfo info) { if (info == StatisticsInfo.EMPTY) return; + if (ApplicationManager.getApplication().isUnitTestMode() && !myTestingStatistics) { + return; + } final String key1 = info.getContext(); int unitNumber = getUnitNumber(key1); @@ -177,9 +183,17 @@ public class StatisticsManagerImpl extends StatisticsManager { } @TestOnly - public void clearStatistics() { - synchronized (LOCK) { - Arrays.fill(myUnits, null); - } + public void enableStatistics(@NotNull Disposable parentDisposable) { + myTestingStatistics = true; + Disposer.register(parentDisposable, new Disposable() { + @Override + public void dispose() { + synchronized (LOCK) { + Arrays.fill(myUnits, null); + } + myTestingStatistics = false; + } + }); } + } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacFullScreenListener.java b/platform/platform-impl/src/com/intellij/ui/mac/MacFullScreenListener.java deleted file mode 100644 index d92a4690be18..000000000000 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacFullScreenListener.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2000-2012 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.ui.mac; - -import com.apple.eawt.AppEvent; -import com.apple.eawt.FullScreenAdapter; -import com.intellij.Patches; -import com.intellij.openapi.wm.impl.IdeFrameImpl; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class MacFullScreenListener extends FullScreenAdapter { - private final MacMainFrameDecorator myDecorator; - private final IdeFrameImpl myFrame; - - public MacFullScreenListener(final MacMainFrameDecorator decorator, - final IdeFrameImpl frame) { - myDecorator = decorator; - myFrame = frame; - } - - @Override - public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) { - myDecorator.setInFullScreen(true); - - JRootPane rootPane = myFrame.getRootPane(); - if (rootPane != null) rootPane.putClientProperty(MacMainFrameDecorator.FULL_SCREEN, Boolean.TRUE); - if (Patches.APPLE_BUG_ID_10207064) { - // fix problem with bottom empty bar - // it seems like the title is still visible in fullscreen but the window itself shifted up for titlebar height - // and the size of the frame is still calculated to be the height of the screen which is wrong - // so just add these titlebar height to the frame height once again - Timer timer = new Timer(300, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - myFrame.setSize(myFrame.getWidth(), myFrame.getHeight() + myFrame.getInsets().top); - } - }); - } - }); - timer.setRepeats(false); - timer.start(); - } - } - - @Override - public void windowExitedFullScreen(AppEvent.FullScreenEvent event) { - myDecorator.setInFullScreen(false); - myFrame.storeFullScreenStateIfNeeded(false); - - JRootPane rootPane = myFrame.getRootPane(); - if (rootPane != null) rootPane.putClientProperty(MacMainFrameDecorator.FULL_SCREEN, null); - } -} diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java index 46d4b8f1836c..fe295604c47b 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java @@ -15,6 +15,9 @@ */ package com.intellij.ui.mac; +import com.apple.eawt.AppEvent; +import com.apple.eawt.FullScreenAdapter; +import com.apple.eawt.FullScreenUtilities; import com.intellij.Patches; import com.intellij.ide.ui.UISettings; import com.intellij.ide.ui.UISettingsListener; @@ -33,6 +36,8 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.concurrent.atomic.AtomicInteger; @@ -145,10 +150,43 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { if (SystemInfo.isMacOSLion) { if (!FULL_SCREEN_AVAILABLE) return; - try { - Class clazz = Class.forName("com.apple.eawt.FullScreenUtilities"); - clazz.getMethod("addFullScreenListenerTo").invoke(null, frame, new MacFullScreenListener(this, frame)); - } catch (Exception ignored) {} + FullScreenUtilities.addFullScreenListenerTo(frame, new FullScreenAdapter() { + @Override + public void windowEnteredFullScreen(AppEvent.FullScreenEvent event) { + myInFullScreen = true; + + JRootPane rootPane = frame.getRootPane(); + if (rootPane != null) rootPane.putClientProperty(FULL_SCREEN, Boolean.TRUE); + if (Patches.APPLE_BUG_ID_10207064) { + // fix problem with bottom empty bar + // it seems like the title is still visible in fullscreen but the window itself shifted up for titlebar height + // and the size of the frame is still calculated to be the height of the screen which is wrong + // so just add these titlebar height to the frame height once again + Timer timer = new Timer(300, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame.setSize(frame.getWidth(), frame.getHeight() + frame.getInsets().top); + } + }); + } + }); + timer.setRepeats(false); + timer.start(); + } + } + + @Override + public void windowExitedFullScreen(AppEvent.FullScreenEvent event) { + myInFullScreen = false; + frame.storeFullScreenStateIfNeeded(false); + + JRootPane rootPane = frame.getRootPane(); + if (rootPane != null) rootPane.putClientProperty(FULL_SCREEN, null); + } + }); } else { // toggle toolbar String className = "IdeaToolbar" + v; @@ -205,8 +243,4 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { invoke(window, "toggleFullScreen:", window); } } - - void setInFullScreen(boolean inFullScreen) { - myInFullScreen = inFullScreen; - } } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 9afcbb16edde..505f4c4bab15 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -126,7 +126,7 @@ public class AbstractPopup implements JBPopup { protected final SpeedSearch mySpeedSearch = new SpeedSearch() { boolean searchFieldShown = false; - protected void update() { + public void update() { mySpeedSearchPatternField.setBackground(new JTextField().getBackground()); onSpeedSearchPatternChanged(); mySpeedSearchPatternField.setText(getFilter()); diff --git a/platform/platform-impl/src/com/intellij/util/ui/ValidatingTableEditor.java b/platform/platform-impl/src/com/intellij/util/ui/ValidatingTableEditor.java index 7c06e6c39075..331903f3b691 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/ValidatingTableEditor.java +++ b/platform/platform-impl/src/com/intellij/util/ui/ValidatingTableEditor.java @@ -190,7 +190,7 @@ public abstract class ValidatingTableEditor implements ComponentWithEmptyT myFixLink = new HoverHyperlinkLabel(null); } - protected ValidatingTableEditor(AnActionButton extraButton) { + protected ValidatingTableEditor(@Nullable AnActionButton ... extraButtons) { ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTable).disableRemoveAction().disableUpAction().disableDownAction(); decorator.setAddAction(new AnActionButtonRunnable() { @@ -211,8 +211,10 @@ public abstract class ValidatingTableEditor implements ComponentWithEmptyT myRemoveButton.setShortcut(CustomShortcutSet.fromString("alt DELETE")); //NON-NLS decorator.addExtraAction(myRemoveButton); - if (extraButton != null) { - decorator.addExtraAction(extraButton); + if (extraButtons != null && extraButtons.length != 0) { + for (AnActionButton extraButton : extraButtons) { + decorator.addExtraAction(extraButton); + } } myTablePanel.add(decorator.createPanel(), BorderLayout.CENTER); @@ -240,6 +242,7 @@ public abstract class ValidatingTableEditor implements ComponentWithEmptyT } protected ValidatingTableEditor() { + //noinspection NullArgumentToVariableArgMethod this(null); } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index dcf12af29677..ec400d719c25 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -69,6 +69,8 @@ action.EditorPasteSimple.description=Paste without formatting, autoimport, liter action.EditorPasteFromX11.text=Paste from X clipboard action.EditorDelete.text=Delete action.EditorBackSpace.text=Backspace +action.EditorHungryBackSpace.text=Hungry Backspace +action.EditorHungryBackSpace.description=Acts as the Backspace except that removes all whitespace symbols before the caret (if any) action.EditorMoveToPageTop.text=Move Caret to Page Top action.EditorMoveToPageBottom.text=Move Caret to Page Bottom action.EditorMoveToPageTopWithSelection.text=Move Caret to Page Top with Selection diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index 82d004cf780e..9fa986238706 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -207,6 +207,9 @@ intention.remove.literal.underscores=Remove underscores from literal intention.insert.literal.underscores=Insert underscores into literal intention.replace.cast.with.var.text=Replace ''{0}'' with ''{1}'' intention.replace.cast.with.var.family=Replace cast with variable +intention.convert.color.representation.text=Convert to ''new Color{0}'' +intention.convert.color.representation.family=Convert Color representation +intention.break.string.on.line.breaks.text=Break string on '\\n' intention.create.test=Create Test @@ -465,7 +468,7 @@ i18nize.empty.file.path=Please specify properties file path choose.type.popup.title=Choose Type cast.expression=Cast expression cast.to.0=Cast to ''{0}'' -class.completion.file.path=Press {0} to search for all matching project files +class.completion.file.path=Press {0} again to search for all matching project files class.completion.file.path.all.variants=Press {0} to search for matching files of any type property.has.more.parameters.than.passed=Property ''{0}'' expected {1} {1, choice, 1#parameter|2#parameters}, passed {2} create.file.family=Create File diff --git a/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties b/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties index 883ebe769e70..14f3326d6b9d 100644 --- a/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties +++ b/platform/platform-resources-en/src/messages/FeatureStatisticsBundle.properties @@ -38,12 +38,9 @@ navigation.select.in=Select In popup navigation.goto.declaration=Go to declaration navigation.goto.implementation=Go to implementation editing.completion.basic=Basic code completion -editing.completion.classname=Class name completion editing.completion.smarttype.general=Smart type completion -editing.completion.smarttype.anonymous=Smart anonymous class instantiation editing.completion.smarttype.afternew=Smart type completion after new editing.completion.smarttype.casting=Smart type casting -editing.completion.second.classname=Second class name completion editing.completion.second.basic=Second basic completion editing.completion.second.smarttype.chain=Second smart type completion: chained method calls editing.completion.second.smarttype.toar=Second smart type completion: toArray() conversion diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties index c476b43c767e..01f60d0a1e09 100644 --- a/platform/platform-resources-en/src/messages/FindBundle.properties +++ b/platform/platform-resources-en/src/messages/FindBundle.properties @@ -76,7 +76,7 @@ find.filter.invalid.file.mask.error=Bad file mask \"{0}\" find.filter.empty.file.mask.error=Empty file mask find.options.case.sensitive=&Case sensitive find.options.replace.preserve.case=Preser&ve case -find.options.whole.words.only=W&hole words only +find.options.whole.words.only=W&hole words only (may be faster) find.options.string.literals.only=S&tring literals only find.options.comments.only=Comm&ents only find.options.regular.expressions=Re&gular expression diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 1801a40ee8e3..3bbfc016da00 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1090,3 +1090,6 @@ whatsnew.action.custom.text=What''s _New in {0} whatsnew.action.custom.description=Find out about the new features in this version of {0} diff.dialog.title=Diff Between ''{0}'' and ''{1}'' +goto.custom.region.command=Go to Custom Region +goto.custom.region.message.dumb.mode=Go to Custom Region action is not available until indices are built. +goto.custom.region.message.unavailable=There are no custom folding regions in the current file. \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 779ff6223685..c955353a1bff 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -49,6 +49,7 @@ inspection.data.flow.nullable.quickfix.option=Suggest @Nullable anno inspection.data.flow.true.asserts.option=Don't report assert statements with condition statically proven to be always true inspection.data.flow.redundant.instanceof.quickfix=Replace with != null inspection.data.flow.simplify.boolean.expression.quickfix=Simplify Boolean Expression +inspection.data.flow.simplify.to.assignment.quickfix.name=Simplify to normal assignment configure.annotations.option=Configure annotations #messages from dataflow inspection diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index a6458b03d218..86fda522dc82 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -141,6 +141,7 @@ refactoring.introduceVariable=Extract Variable refactoring refactoring.introduce.selection.error=Cannot perform refactoring using selected element(s) refactoring.introduce.name.error=Incorrect name refactoring.introduce.name.used.error=This name is already used +refactoring.introduce.variable.scope.error=Name clashes with existing variable refactoring.introduce.placing.error=Cannot extract {0} variable variable.of.type=Variable of &type: diff --git a/platform/platform-resources-en/src/tips/TagNameCompletion.html b/platform/platform-resources-en/src/tips/TagNameCompletion.html index 69668ea3624d..cdce27443c63 100644 --- a/platform/platform-resources-en/src/tips/TagNameCompletion.html +++ b/platform/platform-resources-en/src/tips/TagNameCompletion.html @@ -3,7 +3,8 @@ -

A special variant of the CodeCompletion feature invoked by &shortcut:ClassNameCompletion; allows you to +

+ A special variant of the Code Completion feature invoked by pressing &shortcut:CodeCompletion; twice allows you to complete XML tag names from namespaces not declared in the current file. If the namespace is not declared yet the declaration is generated automatically. diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 78eedf74f4ef..bd57ac5cbe59 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -51,7 +51,7 @@ serviceImplementation="com.intellij.application.options.CodeStyleSettingsUtilImpl"/> + serviceImplementation="com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil"/> + diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index 801ea6a0fbfb..368f63db950d 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -406,6 +406,9 @@ + + + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 7422ec6184f8..19469e244507 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -178,6 +178,7 @@ + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index ee0461368bd7..bd266acce041 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -41,6 +41,7 @@ + diff --git a/platform/platform-tests/testSrc/com/intellij/statistics/StatisticsManagerTest.java b/platform/platform-tests/testSrc/com/intellij/statistics/StatisticsManagerTest.java index 8e85860d83c8..4087b43e3cad 100644 --- a/platform/platform-tests/testSrc/com/intellij/statistics/StatisticsManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/statistics/StatisticsManagerTest.java @@ -19,22 +19,16 @@ public class StatisticsManagerTest extends LightPlatformTestCase { @Override protected void setUp() throws Exception { super.setUp(); - ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics(); + ((StatisticsManagerImpl)StatisticsManager.getInstance()).enableStatistics(getTestRootDisposable()); } - @Override - protected void tearDown() throws Exception { - ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics(); - super.tearDown(); - } - - private void incUseCount(String value, int times) { + private static void incUseCount(String value, int times) { for (int i = 0; i < times; i++) { StatisticsManager.getInstance().incUseCount(new StatisticsInfo(TEST_CONTEXT, value)); } } - private int getUseCount(String value) { + private static int getUseCount(String value) { return StatisticsManager.getInstance().getUseCount(new StatisticsInfo(TEST_CONTEXT, value)); } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentFolderBaseImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentFolderBaseImpl.java index 07e54aab89dc..7c2664f91de5 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentFolderBaseImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ContentFolderBaseImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -73,6 +73,9 @@ public abstract class ContentFolderBaseImpl extends RootModelComponentBase imple @Override public VirtualFile getFile() { + if (!myFilePointer.isValid()) { + return null; + } final VirtualFile file = myFilePointer.getFile(); return file == null || !file.isDirectory() ? null : file; } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index c8833bd7de58..24c85967cdd1 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -420,12 +420,13 @@ public class SMTestProxy extends AbstractTestProxy { public void printOn(final Printer printer) { final Printer rightPrinter = getRightPrinter(printer); super.printOn(rightPrinter); + final AbstractState oldState = myState; invokeInAlarm(new Runnable() { @Override public void run() { //Tests State, that provide and formats additional output - myState.printOn(rightPrinter); + oldState.printOn(rightPrinter); } }); } diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java index 15aab99d6495..6d3ec85e2459 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -46,7 +46,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.impl.source.PostprocessReformattingAspect; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.rt.execution.junit.FileComparisonFailure; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -225,7 +225,7 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest } private static void setupEditorForInjectedLanguage() { - Editor editor = InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(myEditor, myFile); + Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, myFile); if (editor instanceof EditorWindow) { myFile = ((EditorWindow)editor).getInjectedFile(); myEditor = editor; @@ -444,13 +444,13 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest return myEditor; } if (dataId.equals(AnActionEvent.injectedId(PlatformDataKeys.EDITOR.getName()))) { - return InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(getEditor(), getFile()); + return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile()); } if (LangDataKeys.PSI_FILE.is(dataId)) { return myFile; } if (dataId.equals(AnActionEvent.injectedId(LangDataKeys.PSI_FILE.getName()))) { - Editor editor = InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(getEditor(), getFile()); + Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile()); return editor instanceof EditorWindow ? ((EditorWindow)editor).getInjectedFile() : getFile(); } return super.getData(dataId); @@ -514,69 +514,69 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest } } protected static void backspace() { - doAction(IdeActions.ACTION_EDITOR_BACKSPACE); + executeAction(IdeActions.ACTION_EDITOR_BACKSPACE); } protected static void delete() { - doAction(IdeActions.ACTION_EDITOR_DELETE); + executeAction(IdeActions.ACTION_EDITOR_DELETE); } protected static void home() { - doAction(IdeActions.ACTION_EDITOR_MOVE_LINE_START); + executeAction(IdeActions.ACTION_EDITOR_MOVE_LINE_START); } protected static void end() { - doAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END); + executeAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END); } protected static void copy() { - doAction(IdeActions.ACTION_EDITOR_COPY); + executeAction(IdeActions.ACTION_EDITOR_COPY); } protected static void paste() { - doAction(IdeActions.ACTION_EDITOR_PASTE); + executeAction(IdeActions.ACTION_EDITOR_PASTE); } protected static void moveCaretToPreviousWordWithSelection() { - doAction("EditorPreviousWordWithSelection"); + executeAction("EditorPreviousWordWithSelection"); } protected static void moveCaretToNextWordWithSelection() { - doAction("EditorNextWordWithSelection"); + executeAction("EditorNextWordWithSelection"); } protected static void cutLineBackward() { - doAction("EditorCutLineBackward"); + executeAction("EditorCutLineBackward"); } protected static void cutToLineEnd() { - doAction("EditorCutLineEnd"); + executeAction("EditorCutLineEnd"); } protected static void killToWordStart() { - doAction("EditorKillToWordStart"); + executeAction("EditorKillToWordStart"); } protected static void killToWordEnd() { - doAction("EditorKillToWordEnd"); + executeAction("EditorKillToWordEnd"); } protected static void killRegion() { - doAction("EditorKillRegion"); + executeAction("EditorKillRegion"); } protected static void killRingSave() { - doAction("EditorKillRingSave"); + executeAction("EditorKillRingSave"); } protected static void unindent() { - doAction("EditorUnindentSelection"); + executeAction("EditorUnindentSelection"); } protected static void lineComment() { new CommentByLineCommentHandler().invoke(getProject(), getEditor(), getFile()); } - private static void doAction(@NotNull final String actionId) { + protected static void executeAction(@NotNull final String actionId) { CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { @Override public void run() { diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 8154d996b0e6..923e91eaed8d 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -68,7 +68,10 @@ import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.*; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.openapi.vfs.encoding.EncodingManagerImpl; import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl; @@ -209,7 +212,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da ByteArrayOutputStream buffer = new ByteArrayOutputStream(); new Throwable(projectFile.getPath()).printStackTrace(new PrintStream(buffer)); - ourProject = PlatformTestCase.createProject(projectFile, LIGHT_PROJECT_MARK +buffer.toString()); + ourProject = PlatformTestCase.createProject(projectFile, LIGHT_PROJECT_MARK + buffer.toString()); if (!ourHaveShutdownHook) { ourHaveShutdownHook = true; registerShutdownHook(); @@ -233,7 +236,10 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da FileBasedIndex.getInstance().registerIndexableSet(new IndexableFileSet() { @Override public boolean isInSet(@NotNull final VirtualFile file) { - return ourSourceRoot != null && file.getFileSystem() == ourSourceRoot.getFileSystem() && ourProject.isOpen(); + return ourSourceRoot != null && + file.getFileSystem() == ourSourceRoot.getFileSystem() && + ourProject != null && + ourProject.isOpen(); } @Override @@ -313,7 +319,8 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da super.setUp(); initApplication(); ourApplication.setDataProvider(this); - doSetup(new SimpleLightProjectDescriptor(getModuleType(), getProjectJDK()), configureLocalInspectionTools(), myAvailableInspectionTools); + doSetup(new SimpleLightProjectDescriptor(getModuleType(), getProjectJDK()), configureLocalInspectionTools(), + myAvailableInspectionTools); ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(getProject())).pushInjectors(); storeSettings(); @@ -326,7 +333,8 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } public static void doSetup(final LightProjectDescriptor descriptor, - final LocalInspectionTool[] localInspectionTools, final Map availableInspectionTools) throws Exception { + final LocalInspectionTool[] localInspectionTools, final Map availableInspectionTools) + throws Exception { assertNull("Previous test " + ourTestCase + " hasn't called tearDown(). Probably overriden without super call.", ourTestCase); IdeaLogger.ourErrorsOccurred = null; @@ -348,7 +356,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da @Override @NotNull public InspectionProfileEntry[] getInspectionTools(PsiElement element) { - if (availableInspectionTools != null){ + if (availableInspectionTools != null) { final Collection tools = availableInspectionTools.values(); return tools.toArray(new InspectionTool[tools.size()]); } @@ -405,7 +413,13 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da catch (Exception e) { } - assertTrue("open: "+getProject().isOpen()+"; disposed:"+getProject().isDisposed()+"; startup passed:"+ passed+"; all open projects: "+ + assertTrue("open: " + + getProject().isOpen() + + "; disposed:" + + getProject().isDisposed() + + "; startup passed:" + + passed + + "; all open projects: " + Arrays.asList(ProjectManager.getInstance().getOpenProjects()), getProject().isInitialized()); CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(new CodeStyleSettings()); @@ -443,8 +457,10 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da private static void enableInspectionTool(final Map availableLocalTools, InspectionTool wrapper) { final String shortName = wrapper.getShortName(); final HighlightDisplayKey key = HighlightDisplayKey.find(shortName); - if (key == null){ - HighlightDisplayKey.register(shortName, wrapper.getDisplayName(), wrapper instanceof LocalInspectionToolWrapper ? ((LocalInspectionToolWrapper)wrapper).getTool().getID() : wrapper.getShortName()); + if (key == null) { + HighlightDisplayKey.register(shortName, wrapper.getDisplayName(), wrapper instanceof LocalInspectionToolWrapper + ? ((LocalInspectionToolWrapper)wrapper).getTool().getID() + : wrapper.getShortName()); } availableLocalTools.put(shortName, wrapper); } @@ -528,7 +544,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da public void run() { ((UndoManagerImpl)UndoManager.getGlobalInstance()).dropHistoryInTests(); ((UndoManagerImpl)UndoManager.getInstance(project)).dropHistoryInTests(); - + UIUtil.dispatchAllInvocationEvents(); } }); @@ -546,7 +562,8 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da checkEditorsReleased(); } if (isLight(project)) { - ((ProjectImpl)project).setTemporarilyDisposed(true); // mark temporarily as disposed so that rogue component trying to access it will fail + ((ProjectImpl)project) + .setTemporarilyDisposed(true); // mark temporarily as disposed so that rogue component trying to access it will fail documentManager.clearUncommitedDocuments(); } } @@ -631,11 +648,11 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } finally { //try{ - tearDown(); + tearDown(); //} //catch(Throwable th){ // noinspection CallToPrintStackTrace - //th.printStackTrace(); + //th.printStackTrace(); //} } } @@ -665,15 +682,18 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da * @param text - file text. * @return dummy psi file. * @throws com.intellij.util.IncorrectOperationException + * */ protected static PsiFile createFile(@NonNls String fileName, @NonNls String text) throws IncorrectOperationException { FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); - return PsiFileFactory.getInstance(getProject()).createFileFromText(fileName, fileType, text, LocalTimeCounter.currentTime(), true, false); + return PsiFileFactory.getInstance(getProject()) + .createFileFromText(fileName, fileType, text, LocalTimeCounter.currentTime(), true, false); } protected static PsiFile createLightFile(@NonNls String fileName, String text) throws IncorrectOperationException { FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); - return PsiFileFactory.getInstance(getProject()).createFileFromText(fileName, fileType, text, LocalTimeCounter.currentTime(), false, false); + return PsiFileFactory.getInstance(getProject()) + .createFileFromText(fileName, fileType, text, LocalTimeCounter.currentTime(), false, false); } /** @@ -795,6 +815,5 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da final String[] newUrls = newSdk.getRootProvider().getUrls(OrderRootType.CLASSES); return CollectionFactory.hashSet(myUrls).equals(CollectionFactory.hashSet(newUrls)); } - } } diff --git a/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java b/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java index 971d52ca8039..7230e1b67f53 100644 --- a/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java +++ b/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java @@ -62,7 +62,7 @@ public class TestLoggerFactory implements Logger.Factory { return; } - final String logDir = PathManager.getSystemPath() + "/" + LOG_DIR; + final String logDir = getTestLogDir(); String text = FileUtil.loadFile(logXmlFile); text = StringUtil.replace(text, SYSTEM_MACRO, StringUtil.replace(PathManager.getSystemPath(), "\\", "\\\\")); text = StringUtil.replace(text, APPLICATION_MACRO, StringUtil.replace(PathManager.getHomePath(), "\\", "\\\\")); @@ -90,4 +90,8 @@ public class TestLoggerFactory implements Logger.Factory { e.printStackTrace(); } } + + public static String getTestLogDir() { + return PathManager.getSystemPath() + "/" + LOG_DIR; + } } \ No newline at end of file diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 01fcccbf1368..49a98fed2b1d 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -367,15 +367,17 @@ public abstract class UsefulTestCase extends TestCase { assertOrderedCollection(Arrays.asList(collection), checkers); } - public static void assertSameElements(@NotNull T[] collection, @NotNull T... expected) { + public static void assertSameElements(T[] collection, T... expected) { assertSameElements(Arrays.asList(collection), expected); } - public static void assertSameElements(@NotNull Collection collection, @NotNull T... expected) { + public static void assertSameElements(Collection collection, T... expected) { assertSameElements(collection, Arrays.asList(expected)); } - public static void assertSameElements(@NotNull Collection collection, @NotNull Collection expected) { + public static void assertSameElements(Collection collection, Collection expected) { + assertNotNull(collection); + assertNotNull(expected); if (collection.size() != expected.size() || !new HashSet(expected).equals(new HashSet(collection))) { Assert.assertEquals(toString(expected, "\n"), toString(collection, "\n")); Assert.assertEquals(new HashSet(expected), new HashSet(collection)); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index e017c1790cc6..74f21c4e530d 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -95,11 +95,9 @@ import com.intellij.psi.impl.cache.CacheManager; import com.intellij.psi.impl.cache.impl.todo.TodoIndex; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.PsiFileImpl; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.UsageSearchContext; -import com.intellij.psi.statistics.StatisticsManager; -import com.intellij.psi.statistics.impl.StatisticsManagerImpl; import com.intellij.psi.stubs.StubUpdatingIndex; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor; @@ -955,7 +953,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @Nullable protected Editor getCompletionEditor() { - return InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(myEditor, myFile); + return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, myFile); } @Override @@ -1050,8 +1048,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @Override public void tearDown() throws Exception { - ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics(); - FileEditorManager editorManager = FileEditorManager.getInstance(getProject()); VirtualFile[] openFiles = editorManager.getOpenFiles(); for (VirtualFile openFile : openFiles) { diff --git a/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java b/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java index 5ca43ada3991..01974698c398 100644 --- a/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java +++ b/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.ThrowableComputable; import com.intellij.util.containers.ConcurrentFactoryMap; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.lang.reflect.*; import java.rmi.Remote; @@ -59,34 +60,23 @@ public class RemoteUtil { } }; + @Nullable + public static T castToRemote(final Object object, final Class clazz) { + if (!Proxy.isProxyClass(object.getClass())) return null; + final InvocationHandler handler = Proxy.getInvocationHandler(object); + if (handler instanceof RemoteInvocationHandler) { + final RemoteInvocationHandler rih = (RemoteInvocationHandler)handler; + if (clazz.isInstance(rih.myRemote)) { + return (T)rih.myRemote; + } + } + return null; + } + public static T castToLocal(final Object remote, final Class clazz) { final ClassLoader loader = clazz.getClassLoader(); - Object proxy = Proxy.newProxyInstance(loader, new Class[]{clazz}, new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (method.getDeclaringClass() == Object.class) { - return method.invoke(remote, args); - } - else { - Method m = ourRemoteToLocalMap.get(Pair., Class>create(remote.getClass(), clazz)).get(method); - if (m == null) throw new NoSuchMethodError(method.getName() + " in " + remote.getClass()); - try { - Object result = m.invoke(remote, args); - if (result instanceof Remote) { - return castToLocal(result, tryFixReturnType(result, method.getReturnType(), loader)); - } - return result; - } - catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException) throw cause; - if (cause instanceof Error) throw cause; - if (canThrow(cause, method)) throw cause; - throw new RuntimeException(cause); - } - } - } - }); - return (T)proxy; + //noinspection unchecked + return (T)Proxy.newProxyInstance(loader, new Class[]{clazz}, new RemoteInvocationHandler(remote, clazz, loader)); } private static Class tryFixReturnType(Object result, Class returnType, ClassLoader loader) throws Exception { @@ -170,4 +160,40 @@ public class RemoteUtil { } return e; } + + private static class RemoteInvocationHandler implements InvocationHandler { + private final Object myRemote; + private final Class myClazz; + private final ClassLoader myLoader; + + public RemoteInvocationHandler(Object remote, Class clazz, ClassLoader loader) { + myRemote = remote; + myClazz = clazz; + myLoader = loader; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getDeclaringClass() == Object.class) { + return method.invoke(myRemote, args); + } + else { + Method m = ourRemoteToLocalMap.get(Pair., Class>create(myRemote.getClass(), myClazz)).get(method); + if (m == null) throw new NoSuchMethodError(method.getName() + " in " + myRemote.getClass()); + try { + Object result = m.invoke(myRemote, args); + if (result instanceof Remote) { + return castToLocal(result, tryFixReturnType(result, method.getReturnType(), myLoader)); + } + return result; + } + catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) throw cause; + if (cause instanceof Error) throw cause; + if (canThrow(cause, method)) throw cause; + throw new RuntimeException(cause); + } + } + } + } } diff --git a/platform/util/src/com/intellij/ui/ClickListener.java b/platform/util/src/com/intellij/ui/ClickListener.java index 9b5346127a77..e7ed54769a99 100644 --- a/platform/util/src/com/intellij/ui/ClickListener.java +++ b/platform/util/src/com/intellij/ui/ClickListener.java @@ -33,28 +33,31 @@ public abstract class ClickListener { public void installOn(final Component c) { myListener = new MouseAdapter() { - private Point clickPoint; + private Point pressPoint; + private Point lastClickPoint; private long lastTimeClicked = -1; private int clickCount = 0; @Override public void mousePressed(MouseEvent e) { - if (Math.abs(lastTimeClicked - e.getWhen()) > TIME_EPS) { + if (Math.abs(lastTimeClicked - e.getWhen()) > TIME_EPS || (lastClickPoint != null && !isWithinEps(lastClickPoint, e.getPoint()))) { clickCount = 0; + lastClickPoint = null; } clickCount++; lastTimeClicked = e.getWhen(); if (!e.isPopupTrigger()) { - clickPoint = e.getPoint(); + pressPoint = e.getPoint(); } } @Override public void mouseReleased(MouseEvent e) { Point releasedAt = e.getPoint(); - Point clickedAt = clickPoint; - clickPoint = null; + Point clickedAt = pressPoint; + lastClickPoint = clickedAt; + pressPoint = null; if (e.isConsumed()) return; @@ -62,7 +65,7 @@ public abstract class ClickListener { if (e.isPopupTrigger()) return; if (releasedAt.x < 0 || releasedAt.y < 0 || releasedAt.x >= c.getWidth() || releasedAt.y >= c.getHeight()) return; - if (Math.abs(clickedAt.x - releasedAt.x) < EPS && Math.abs(clickedAt.y - releasedAt.y) < EPS) { + if (isWithinEps(releasedAt, clickedAt)) { if (onClick(e, clickCount)) { e.consume(); } @@ -73,6 +76,10 @@ public abstract class ClickListener { c.addMouseListener(myListener); } + private static boolean isWithinEps(Point releasedAt, Point clickedAt) { + return Math.abs(clickedAt.x - releasedAt.x) < EPS && Math.abs(clickedAt.y - releasedAt.y) < EPS; + } + public void uninstall(Component c) { c.removeMouseListener(myListener); } diff --git a/platform/util/src/com/intellij/util/CommonProcessors.java b/platform/util/src/com/intellij/util/CommonProcessors.java index e0b3492610ae..0d0a6033b235 100644 --- a/platform/util/src/com/intellij/util/CommonProcessors.java +++ b/platform/util/src/com/intellij/util/CommonProcessors.java @@ -59,19 +59,6 @@ public class CommonProcessors { return myCollection; } - public static class Sync extends CollectProcessor { - public Sync(final Collection collection) { - super(collection); - } - - public Sync() { - } - - @Override - public synchronized boolean process(final T t) { - return super.process(t); - } - } } @NotNull diff --git a/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java b/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java index f19ee9881643..31c3b4f81205 100644 --- a/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java +++ b/platform/util/src/com/intellij/util/io/DataInputOutputUtil.java @@ -38,12 +38,10 @@ public class DataInputOutputUtil { public static void writeNAME(DataOutput record, final String name, AbstractStringEnumerator nameStore) throws IOException { final int nameId = name != null ? nameStore.enumerate(name) : 0; - record.writeByte(nameId & 0xFF); - writeINT(record, (nameId >> 8)); + writeINT(record, nameId); } public static void skipNAME(DataInput record) throws IOException { - record.readUnsignedByte(); readINT(record); } diff --git a/platform/util/src/com/intellij/util/io/StringRef.java b/platform/util/src/com/intellij/util/io/StringRef.java index a45c08e93bba..d2b8c281aef1 100644 --- a/platform/util/src/com/intellij/util/io/StringRef.java +++ b/platform/util/src/com/intellij/util/io/StringRef.java @@ -99,8 +99,7 @@ public class StringRef { } public static StringRef fromStream(DataInput in, AbstractStringEnumerator store) throws IOException { - final int low = in.readUnsignedByte(); - final int nameId = (DataInputOutputUtil.readINT(in) << 8) | low; + final int nameId = DataInputOutputUtil.readINT(in); return nameId != 0 ? new StringRef(nameId, store) : null; } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/EditInjectionSettingsAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/EditInjectionSettingsAction.java index ee119a8a08e1..cc97dfd8c000 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/EditInjectionSettingsAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/EditInjectionSettingsAction.java @@ -26,7 +26,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiLanguageInjectionHost; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.FileContentUtil; import com.intellij.util.IncorrectOperationException; import org.intellij.plugins.intelliLang.Configuration; @@ -53,7 +53,7 @@ public class EditInjectionSettingsAction implements IntentionAction, LowPriority public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { final int offset = editor.getCaretModel().getOffset(); - final PsiFile psiFile = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(file, offset); + final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset); if (psiFile == null) return false; final LanguageInjectionSupport support = psiFile.getUserData(LanguageInjectionSupport.SETTINGS_EDITOR); return support != null; @@ -68,7 +68,7 @@ public class EditInjectionSettingsAction implements IntentionAction, LowPriority } private static void invokeImpl(Project project, Editor editor, PsiFile file) { - final PsiFile psiFile = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(file, editor.getCaretModel().getOffset()); + final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, editor.getCaretModel().getOffset()); if (psiFile == null) return; final PsiLanguageInjectionHost host = InjectedLanguageManager.getInstance(project).getInjectionHost(psiFile); if (host == null) return; diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java index ff564b8899f7..78986215c8a8 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java @@ -16,7 +16,7 @@ package org.intellij.plugins.intelliLang.inject; import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.Language; @@ -65,7 +65,7 @@ public class InjectLanguageAction implements IntentionAction { public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { final PsiLanguageInjectionHost host = findInjectionHost(editor, file); if (host == null) return false; - final List> injectedPsi = InjectedLanguageFacadeImpl.getInstance().getInjectedPsiFiles(host); + final List> injectedPsi = InjectedLanguageUtil.getInstance().getInjectedPsiFiles(host); return injectedPsi == null || injectedPsi.isEmpty(); } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/UnInjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/UnInjectLanguageAction.java index 3829287efc27..c079935c2010 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/UnInjectLanguageAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/UnInjectLanguageAction.java @@ -28,7 +28,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiLanguageInjectionHost; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.FileContentUtil; import com.intellij.util.IncorrectOperationException; import gnu.trove.THashSet; @@ -55,7 +55,7 @@ public class UnInjectLanguageAction implements IntentionAction, LowPriorityActio public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { final int offset = editor.getCaretModel().getOffset(); - final PsiFile psiFile = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(file, offset); + final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset); if (psiFile == null) return false; final LanguageInjectionSupport support = psiFile.getUserData(LanguageInjectionSupport.INJECTOR_SUPPORT); return support != null; @@ -70,7 +70,7 @@ public class UnInjectLanguageAction implements IntentionAction, LowPriorityActio } private static void invokeImpl(Project project, Editor editor, PsiFile file) { - final PsiFile psiFile = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(file, editor.getCaretModel().getOffset()); + final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, editor.getCaretModel().getOffset()); if (psiFile == null) return; final PsiLanguageInjectionHost host = InjectedLanguageManager.getInstance(project).getInjectionHost(psiFile); if (host == null) return; @@ -88,7 +88,7 @@ public class UnInjectLanguageAction implements IntentionAction, LowPriorityActio private static boolean defaultFunctionalityWorked(final PsiLanguageInjectionHost host) { final THashSet languages = new THashSet(); - final List> files = InjectedLanguageFacadeImpl.getInstance().getInjectedPsiFiles(host); + final List> files = InjectedLanguageUtil.getInstance().getInjectedPsiFiles(host); if (files == null) return false; for (Pair pair : files) { for (Language lang = pair.first.getLanguage(); lang != null; lang = lang.getBaseLanguage()) { diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/comment/CommentOnLineWithSourcePredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/comment/CommentOnLineWithSourcePredicate.java index ed366ec1b1ef..a76a86fedbbe 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/comment/CommentOnLineWithSourcePredicate.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/comment/CommentOnLineWithSourcePredicate.java @@ -16,7 +16,7 @@ package com.siyeh.ipp.comment; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -37,7 +37,7 @@ class CommentOnLineWithSourcePredicate implements PsiElementPredicate { } final PsiComment comment = (PsiComment)element; - if (comment instanceof PsiLanguageInjectionHost && InjectedLanguageFacadeImpl.hasInjections((PsiLanguageInjectionHost)comment)) { + if (comment instanceof PsiLanguageInjectionHost && InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost)comment)) { return false; } final IElementType type = comment.getTokenType(); diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java index 9efdeaf805a6..9e0b492f28cb 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java @@ -31,21 +31,19 @@ import java.util.Map; public class ReplaceOperatorAssignmentWithAssignmentIntention extends MutablyNamedIntention { - private static final Map tokenMap = new HashMap(); - - static { - tokenMap.put(JavaTokenType.PLUSEQ, JavaTokenType.PLUS); - tokenMap.put(JavaTokenType.MINUSEQ, JavaTokenType.MINUS); - tokenMap.put(JavaTokenType.ASTERISKEQ, JavaTokenType.ASTERISK); - tokenMap.put(JavaTokenType.DIVEQ, JavaTokenType.DIV); - tokenMap.put(JavaTokenType.ANDEQ, JavaTokenType.AND); - tokenMap.put(JavaTokenType.OREQ, JavaTokenType.OR); - tokenMap.put(JavaTokenType.XOREQ, JavaTokenType.XOR); - tokenMap.put(JavaTokenType.PERCEQ, JavaTokenType.PERC); - tokenMap.put(JavaTokenType.LTLTEQ, JavaTokenType.LTLT); - tokenMap.put(JavaTokenType.GTGTEQ, JavaTokenType.GTGT); - tokenMap.put(JavaTokenType.GTGTGTEQ, JavaTokenType.GTGTGT); - } + private static final Map tokenMap = new HashMap() {{ + put(JavaTokenType.PLUSEQ, JavaTokenType.PLUS); + put(JavaTokenType.MINUSEQ, JavaTokenType.MINUS); + put(JavaTokenType.ASTERISKEQ, JavaTokenType.ASTERISK); + put(JavaTokenType.DIVEQ, JavaTokenType.DIV); + put(JavaTokenType.ANDEQ, JavaTokenType.AND); + put(JavaTokenType.OREQ, JavaTokenType.OR); + put(JavaTokenType.XOREQ, JavaTokenType.XOR); + put(JavaTokenType.PERCEQ, JavaTokenType.PERC); + put(JavaTokenType.LTLTEQ, JavaTokenType.LTLT); + put(JavaTokenType.GTGTEQ, JavaTokenType.GTGT); + put(JavaTokenType.GTGTGTEQ, JavaTokenType.GTGTGT); + }}; @Override @NotNull diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java index 060aa7b71f82..e67384ab57f7 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java @@ -364,7 +364,7 @@ public class ModelParser extends XmlRecursiveElementVisitor { if (myRootComponent == null) { myRootComponent = createComponent(myXmlFile.getRootTag(), myMetaManager.getModelByTag("")); } - else if (session.getRootViews().size() == 1) { + else if (myRootComponent.getMetaModel() != myMetaManager.getModelByTag("merge")) { RadViewComponent rootComponent = myRootComponent; myRootComponent = createComponent(myXmlFile.getRootTag(), myMetaManager.getModelByTag("")); myRootComponent.add(rootComponent, null); diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadCustomViewComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadCustomViewComponent.java index 8c5ddb5ec3fe..e1f0a6e4a45e 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadCustomViewComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadCustomViewComponent.java @@ -25,7 +25,6 @@ import com.intellij.designer.model.MetaModel; import com.intellij.designer.model.RadComponent; import com.intellij.designer.propertyTable.Property; import com.intellij.designer.propertyTable.PropertyTable; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.xml.XmlTag; @@ -71,7 +70,7 @@ public class RadCustomViewComponent extends RadViewComponent implements IConfigu new ChooseClassDialog(moduleProvider.getModule(), "Views", false, "android.view.View"); dialog.show(); - if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + if (dialog.isOK()) { return dialog.getClassName(); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadFragment.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadFragment.java index aa5b172006ae..78fcf85129f9 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadFragment.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadFragment.java @@ -24,7 +24,6 @@ import com.intellij.designer.ModuleProvider; import com.intellij.designer.model.RadComponent; import com.intellij.designer.propertyTable.Property; import com.intellij.designer.propertyTable.editors.TextEditor; -import com.intellij.openapi.ui.DialogWrapper; import org.jetbrains.android.dom.attrs.AttributeFormat; import org.jetbrains.annotations.Nullable; @@ -86,7 +85,7 @@ public class RadFragment extends RadViewComponent implements IConfigurableCompon new ChooseClassDialog(moduleProvider.getModule(), "Fragments", true, "android.app.Fragment", "android.support.v4.app.Fragment"); dialog.show(); - if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + if (dialog.isOK()) { return dialog.getClassName(); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadIncludeLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadIncludeLayout.java index 8dfc12729da3..25c18d6113c4 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadIncludeLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadIncludeLayout.java @@ -41,7 +41,7 @@ public class RadIncludeLayout extends RadViewComponent implements IConfigurableC public void configure(RadComponent rootComponent) throws Exception { ModuleProvider moduleProvider = rootComponent.getClientProperty(ModelParser.MODULE_KEY); - ResourceDialog dialog = new ResourceDialog(moduleProvider.getModule(), IncludeLayoutProperty.TYPES, null); + ResourceDialog dialog = new ResourceDialog(moduleProvider.getModule(), IncludeLayoutProperty.TYPES, null, null); dialog.show(); if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ChooseClassDialog.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ChooseClassDialog.java index 23b901043cb0..67df90be0adf 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ChooseClassDialog.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ChooseClassDialog.java @@ -80,7 +80,7 @@ public class ChooseClassDialog extends DialogWrapper implements ListSelectionLis }; setTitle(title); - getOKAction().setEnabled(false); + setOKActionEnabled(false); init(); } @@ -119,7 +119,7 @@ public class ChooseClassDialog extends DialogWrapper implements ListSelectionLis @Override public void valueChanged(ListSelectionEvent e) { PsiClass psiClass = (PsiClass)myList.getSelectedValue(); - getOKAction().setEnabled(psiClass != null); + setOKActionEnabled(psiClass != null); myResultClassName = psiClass == null ? null : psiClass.getQualifiedName(); } } diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ExtractStyleDialog.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ExtractStyleDialog.java new file mode 100644 index 000000000000..705f7cf6ef0c --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ExtractStyleDialog.java @@ -0,0 +1,240 @@ +/* + * Copyright 2000-2012 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.android.designer.propertyTable.editors; + +import com.android.resources.ResourceType; +import com.intellij.openapi.actionSystem.ActionToolbarPosition; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.ValidationInfo; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlTag; +import com.intellij.ui.*; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.util.PlatformIcons; +import com.intellij.util.containers.Convertor; +import com.intellij.util.ui.tree.TreeUtil; +import org.jetbrains.android.actions.CreateXmlResourceDialog; +import org.jetbrains.android.util.AndroidResourceUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class ExtractStyleDialog extends DialogWrapper { + private final Module myModule; + private final String myFileName; + private final List myDirNames; + + private final JPanel myPanel; + private final JTextField myNameText; + private final CheckboxTree myTree; + + private final CheckedTreeNode myRootNode; + + public ExtractStyleDialog(Module module, String fileName, List dirNames, XmlTag tag) { + super(module.getProject()); + myModule = module; + myFileName = fileName; + myDirNames = dirNames; + + myPanel = new JPanel(new GridLayoutManager(3, 2)); + + JLabel nameLabel = new JLabel("Style name:"); + nameLabel.setDisplayedMnemonic('n'); + myPanel.add(nameLabel, + new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, 0, 0, null, null, null)); + + myNameText = new JTextField(); + myPanel.add(myNameText, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, + GridConstraints.SIZEPOLICY_CAN_GROW, 0, null, null, null)); + + nameLabel.setLabelFor(myNameText); + + myNameText.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + checkFinish(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + checkFinish(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + checkFinish(); + } + }); + + JLabel attributesLabel = new JLabel("Attributes:"); + attributesLabel.setDisplayedMnemonic('A'); + myPanel.add(attributesLabel, + new GridConstraints(1, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, 0, 0, null, null, null)); + + myRootNode = new CheckedTreeNode(null); + for (XmlAttribute attribute : tag.getAttributes()) { + String name = attribute.getName(); + if (!"style".equalsIgnoreCase(name)) { + CheckedTreeNode treeNode = new CheckedTreeNode(attribute); + treeNode.setChecked(!"android:layout_width".equalsIgnoreCase(name) && !"android:layout_height".equalsIgnoreCase(name)); + myRootNode.add(treeNode); + } + } + + CheckboxTree.CheckboxTreeCellRenderer renderer = new CheckboxTree.CheckboxTreeCellRenderer() { + @Override + public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + if (value instanceof CheckedTreeNode) { + XmlAttribute attribute = (XmlAttribute)((CheckedTreeNode)value).getUserObject(); + if (attribute != null) { + getTextRenderer().append(attribute.getLocalName()); + getTextRenderer().append(" [" + attribute.getValue() + "]", SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES); + } + } + } + }; + myTree = new CheckboxTree(renderer, myRootNode) { + @Override + protected void onNodeStateChanged(CheckedTreeNode node) { + checkFinish(); + } + + protected void installSpeedSearch() { + new TreeSpeedSearch(this, new Convertor() { + public String convert(TreePath path) { + Object object = path.getLastPathComponent(); + if (object instanceof CheckedTreeNode) { + XmlAttribute attribute = (XmlAttribute)((CheckedTreeNode)object).getUserObject(); + if (attribute != null) { + return attribute.getLocalName(); + } + } + return ""; + } + }); + } + }; + myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + myTree.setRootVisible(false); + myTree.setShowsRootHandles(false); + TreeUtil.expandAll(myTree); + + attributesLabel.setLabelFor(myTree); + + ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTree); + decorator.setToolbarPosition(ActionToolbarPosition.RIGHT); + decorator.setEditAction(null); + decorator.disableUpDownActions(); + + AnActionButton selectAll = new AnActionButton("Select All", null, PlatformIcons.SELECT_ALL_ICON) { + @Override + public void actionPerformed(AnActionEvent e) { + setChecked(true); + } + }; + decorator.addExtraAction(selectAll); + + AnActionButton unselectAll = new AnActionButton("Unselect All", null, PlatformIcons.UNSELECT_ALL_ICON) { + @Override + public void actionPerformed(AnActionEvent e) { + setChecked(false); + } + }; + decorator.addExtraAction(unselectAll); + + + myPanel.add(decorator.createPanel(), + new GridConstraints(2, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, + GridConstraints.SIZEPOLICY_CAN_GROW, 0, null, null, null)); + + myPanel.setPreferredSize(new Dimension(400, -1)); + + setTitle("Extract Style"); + checkFinish(); + init(); + } + + private void checkFinish() { + if (AndroidResourceUtil.isCorrectAndroidResourceName(myNameText.getText().trim())) { + int count = myRootNode.getChildCount(); + for (int i = 0; i < count; i++) { + CheckedTreeNode treeNode = (CheckedTreeNode)myRootNode.getChildAt(i); + if (treeNode.isChecked()) { + setOKActionEnabled(true); + return; + } + } + } + setOKActionEnabled(false); + } + + private void setChecked(boolean value) { + int count = myRootNode.getChildCount(); + for (int i = 0; i < count; i++) { + ((CheckedTreeNode)myRootNode.getChildAt(i)).setChecked(value); + } + myTree.repaint(); + checkFinish(); + } + + @Override + protected JComponent createCenterPanel() { + return myPanel; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myNameText; + } + + @Override + protected ValidationInfo doValidate() { + return CreateXmlResourceDialog.checkIfResourceAlreadyExists(myModule, getStyleName(), ResourceType.STYLE, myDirNames, myFileName); + } + + @NotNull + public String getStyleName() { + return myNameText.getText(); + } + + @NotNull + public List getStyledAttributes() { + List attributes = new ArrayList(); + + int count = myRootNode.getChildCount(); + for (int i = 0; i < count; i++) { + CheckedTreeNode treeNode = (CheckedTreeNode)myRootNode.getChildAt(i); + if (treeNode.isChecked()) { + attributes.add((XmlAttribute)treeNode.getUserObject()); + } + } + + return attributes; + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java index e2803d2928b4..9ec76683bcd1 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java @@ -15,7 +15,9 @@ */ package com.intellij.android.designer.propertyTable.editors; +import com.android.resources.ResourceFolderType; import com.android.resources.ResourceType; +import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.propertyTable.renderers.ResourceRenderer; import com.intellij.designer.componentTree.TreeNodeDescriptor; import com.intellij.icons.AllIcons; @@ -23,19 +25,30 @@ import com.intellij.ide.util.treeView.AbstractTreeBuilder; import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.ide.util.treeView.NodeRenderer; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.xml.XmlAttribute; import com.intellij.ui.*; import com.intellij.ui.components.JBTabbedPane; import com.intellij.ui.speedSearch.SpeedSearchUtil; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.ArrayUtil; import com.intellij.util.ui.tree.TreeUtil; +import org.jetbrains.android.actions.CreateResourceFileAction; +import org.jetbrains.android.actions.CreateXmlResourceDialog; import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.resourceManagers.ResourceManager; import org.jetbrains.android.util.AndroidCommonUtils; +import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -60,23 +73,53 @@ import java.util.List; */ public class ResourceDialog extends DialogWrapper implements TreeSelectionListener { private static final String ANDROID = "@android:"; + private static final String TYPE_KEY = "ResourceType"; private static final Icon RESOURCE_ITEM_ICON = AllIcons.Css.Property; + private final Module myModule; + private final RadViewComponent myComponent; + private final JBTabbedPane myContentPanel; private final ResourcePanel myProjectPanel; private final ResourcePanel mySystemPanel; private ColorPicker myColorPicker; - private final Action myNewResourceAction = new AbstractAction("New Resource...") { + + private final Action myNewResourceAction = new AbstractAction("New Resource", AllIcons.General.ComboArrowDown) { @Override public void actionPerformed(ActionEvent e) { - // TODO: Auto-generated method stub + JComponent component = (JComponent)e.getSource(); + ActionPopupMenu popupMenu = createNewResourcePopupMenu(); + popupMenu.getComponent().show(component, 0, component.getHeight()); } }; + private final AnAction myNewResourceValueAction = new AnAction() { + @Override + public void actionPerformed(AnActionEvent e) { + ResourceType type = (ResourceType)getTemplatePresentation().getClientProperty(TYPE_KEY); + createNewResourceValue(type); + } + }; + private final AnAction myNewResourceFileAction = new AnAction() { + @Override + public void actionPerformed(AnActionEvent e) { + ResourceType type = (ResourceType)getTemplatePresentation().getClientProperty(TYPE_KEY); + createNewResourceFile(type); + } + }; + private final AnAction myExtractStyleAction = new AnAction("Extract Style...") { + @Override + public void actionPerformed(AnActionEvent e) { + extractStyle(); + } + }; + private String myResultResourceName; - public ResourceDialog(Module module, ResourceType[] types, String value) { + public ResourceDialog(Module module, ResourceType[] types, String value, RadViewComponent component) { super(module.getProject()); + myModule = module; + myComponent = component; setTitle("Resources"); @@ -123,13 +166,126 @@ public class ResourceDialog extends DialogWrapper implements TreeSelectionListen myContentPanel.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - myNewResourceAction.setEnabled(myContentPanel.getSelectedComponent() == myProjectPanel.myComponent); valueChanged(null); } }); - init(); valueChanged(null); + init(); + } + + private ActionPopupMenu createNewResourcePopupMenu() { + ActionManager actionManager = ActionManager.getInstance(); + DefaultActionGroup actionGroup = new DefaultActionGroup(); + + ResourceGroup resourceGroup = getSelectedElement(myProjectPanel.myTreeBuilder, ResourceGroup.class); + if (resourceGroup == null) { + resourceGroup = getSelectedElement(myProjectPanel.myTreeBuilder, ResourceItem.class).getGroup(); + } + + if (AndroidResourceUtil.VALUE_RESOURCE_TYPES.contains(resourceGroup.getType())) { + myNewResourceValueAction.getTemplatePresentation().setText("New " + resourceGroup + " Value..."); + myNewResourceValueAction.getTemplatePresentation().putClientProperty(TYPE_KEY, resourceGroup.getType()); + actionGroup.add(myNewResourceValueAction); + } + if (AndroidResourceUtil.XML_FILE_RESOURCE_TYPES.contains(resourceGroup.getType())) { + myNewResourceFileAction.getTemplatePresentation().setText("New " + resourceGroup + " File..."); + myNewResourceFileAction.getTemplatePresentation().putClientProperty(TYPE_KEY, resourceGroup.getType()); + actionGroup.add(myNewResourceFileAction); + } + if (myComponent != null && ResourceType.STYLE.equals(resourceGroup.getType()) && myComponent.getTag().getAttributes().length > 0) { + // TODO: add StyleItem + //actionGroup.add(myExtractStyleAction); + } + + return actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, actionGroup); + } + + private void createNewResourceValue(ResourceType resourceType) { + CreateXmlResourceDialog dialog = new CreateXmlResourceDialog(myModule, resourceType, null, null, true); + dialog.setTitle("New " + StringUtil.capitalize(resourceType.getDisplayName()) + " Value Resource"); + dialog.show(); + + if (!dialog.isOK()) { + return; + } + + Module moduleToPlaceResource = dialog.getModule(); + if (moduleToPlaceResource == null) { + return; + } + + String fileName = dialog.getFileName(); + List dirNames = dialog.getDirNames(); + String resValue = dialog.getValue(); + String resName = dialog.getResourceName(); + if (!AndroidResourceUtil.createValueResource(moduleToPlaceResource, resName, resourceType, fileName, dirNames, resValue)) { + return; + } + + PsiDocumentManager.getInstance(myModule.getProject()).commitAllDocuments(); + + myResultResourceName = "@" + resourceType.getName() + "/" + resName; + close(OK_EXIT_CODE); + } + + private void createNewResourceFile(ResourceType resourceType) { + AndroidFacet facet = AndroidFacet.getInstance(myModule); + PsiElement[] elements = CreateResourceFileAction.createFileResource(facet, resourceType, null, true); + + if (elements.length == 1) { + String name = ((PsiFile)elements[0]).getName(); + int index = name.lastIndexOf('.'); + if (index != -1) { + name = name.substring(0, index); + } + myResultResourceName = "@" + resourceType.getName() + "/" + name; + close(OK_EXIT_CODE); + } + } + + private void extractStyle() { + String fileName = AndroidResourceUtil.getDefaultResourceFileName(ResourceType.STYLE); + + VirtualFile[] dirs = {AndroidRootUtil.getResourceDir(AndroidFacet.getInstance(myModule))}; + List subDirs = AndroidResourceUtil.getResourceSubdirs(ResourceFolderType.VALUES.getName(), dirs); + List dirNames = new ArrayList(); + for (VirtualFile dir : subDirs) { + dirNames.add(dir.getName()); + } + + ExtractStyleDialog dialog = new ExtractStyleDialog(myModule, fileName, dirNames, myComponent.getTag()); + dialog.show(); + + if (!dialog.isOK()) { + return; + } + + final List attributes = dialog.getStyledAttributes(); + + StringBuilder value = new StringBuilder(); + for (XmlAttribute attribute : attributes) { + value.append("").append(attribute.getValue()).append("\n"); + } + + String resName = dialog.getStyleName(); + if (!AndroidResourceUtil.createValueResource(myModule, resName, ResourceType.STYLE, fileName, dirNames, value.toString())) { + return; + } + + PsiDocumentManager.getInstance(myModule.getProject()).commitAllDocuments(); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + for (XmlAttribute attribute : attributes) { + attribute.delete(); + } + } + }); + + myResultResourceName = "@style/" + resName; + close(OK_EXIT_CODE); } @Override @@ -144,7 +300,7 @@ public class ResourceDialog extends DialogWrapper implements TreeSelectionListen @Override protected Action[] createLeftSideActions() { - return super.createLeftSideActions();//new Action[]{myNewResourceAction}; + return new Action[]{myNewResourceAction}; } @Override @@ -164,26 +320,35 @@ public class ResourceDialog extends DialogWrapper implements TreeSelectionListen super.doOKAction(); } + @Nullable + private static T getSelectedElement(AbstractTreeBuilder treeBuilder, Class elementClass) { + Set elements = treeBuilder.getSelectedElements(elementClass); + return elements.isEmpty() ? null : elements.iterator().next(); + } + @Override public void valueChanged(@Nullable TreeSelectionEvent e) { Component selectedComponent = myContentPanel.getSelectedComponent(); if (selectedComponent == myColorPicker) { Color color = myColorPicker.getColor(); - getOKAction().setEnabled(color != null); + setOKActionEnabled(color != null); + myNewResourceAction.setEnabled(false); myResultResourceName = color == null ? null : "#" + toHex(color.getRed()) + toHex(color.getGreen()) + toHex(color.getBlue()); } else { - ResourcePanel panel = selectedComponent == myProjectPanel.myComponent ? myProjectPanel : mySystemPanel; - Set elements = panel.myTreeBuilder.getSelectedElements(ResourceItem.class); - getOKAction().setEnabled(!elements.isEmpty()); + boolean isProjectPanel = selectedComponent == myProjectPanel.myComponent; + ResourcePanel panel = isProjectPanel ? myProjectPanel : mySystemPanel; + ResourceItem element = getSelectedElement(panel.myTreeBuilder, ResourceItem.class); + setOKActionEnabled(element != null); + myNewResourceAction.setEnabled(isProjectPanel && !panel.myTreeBuilder.getSelectedElements().isEmpty()); - if (elements.isEmpty()) { + if (element == null) { myResultResourceName = null; } else { String prefix = panel == myProjectPanel ? "@" : ANDROID; - myResultResourceName = prefix + elements.iterator().next().getName(); + myResultResourceName = prefix + element.getName(); } } } @@ -316,6 +481,10 @@ public class ResourceDialog extends DialogWrapper implements TreeSelectionListen }); } + public ResourceType getType() { + return myType; + } + public String getName() { return myType.getName(); } diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceEditor.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceEditor.java index 0f08b55dad2b..575519304e52 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceEditor.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceEditor.java @@ -17,6 +17,7 @@ package com.intellij.android.designer.propertyTable.editors; import com.android.resources.ResourceType; import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; import com.intellij.designer.ModuleProvider; import com.intellij.designer.model.RadComponent; import com.intellij.designer.propertyTable.InplaceContext; @@ -26,7 +27,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComponentWithBrowseButton; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ComboboxWithBrowseButton; @@ -50,6 +50,7 @@ public class ResourceEditor extends PropertyEditor { private final ResourceType[] myTypes; private ComponentWithBrowseButton myEditor; protected RadComponent myRootComponent; + private RadComponent myComponent; private JCheckBox myCheckBox; private final Border myCheckBoxBorder = new JTextField().getBorder(); private boolean myIgnoreCheckBoxValue; @@ -207,6 +208,7 @@ public class ResourceEditor extends PropertyEditor { Object object, @Nullable InplaceContext inplaceContext) { myRootComponent = rootComponent; + myComponent = component; String value = (String)object; JTextField text = getComboText(); @@ -270,10 +272,10 @@ public class ResourceEditor extends PropertyEditor { protected void showDialog() { ModuleProvider moduleProvider = myRootComponent.getClientProperty(ModelParser.MODULE_KEY); - ResourceDialog dialog = new ResourceDialog(moduleProvider.getModule(), myTypes, (String)getValue()); + ResourceDialog dialog = new ResourceDialog(moduleProvider.getModule(), myTypes, (String)getValue(), (RadViewComponent)myComponent); dialog.show(); - if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + if (dialog.isOK()) { setValue(dialog.getResourceName()); } else if (myBooleanResourceValue != null) { diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java index 13ca21a45c5d..b6c2a0650fb0 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceFileAction.java @@ -94,7 +94,7 @@ public class CreateResourceFileAction extends CreateElementActionBase { @NotNull public static PsiElement[] createFileResource(@NotNull AndroidFacet facet, @NotNull final ResourceType resType, - @NotNull String resName, + @Nullable String resName, boolean chooseResName) { final CreateResourceFileAction action = getInstance(); diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java index c40f66ff5189..de177fd26377 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java @@ -344,7 +344,7 @@ public class CreateXmlResourceDialog extends DialogWrapper { } @Nullable - private static ValidationInfo checkIfResourceAlreadyExists(@NotNull Module selectedModule, + public static ValidationInfo checkIfResourceAlreadyExists(@NotNull Module selectedModule, @NotNull String resourceName, @NotNull ResourceType resourceType, @NotNull List dirNames, diff --git a/plugins/android/testSrc/org/jetbrains/android/AndroidRenameTest.java b/plugins/android/testSrc/org/jetbrains/android/AndroidRenameTest.java index 0cf268f4b7a5..e51b34026cfb 100644 --- a/plugins/android/testSrc/org/jetbrains/android/AndroidRenameTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/AndroidRenameTest.java @@ -27,7 +27,7 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.actions.RenameElementAction; @@ -106,7 +106,7 @@ public class AndroidRenameTest extends AndroidTestCase { protected void run() throws Throwable { Editor editor = myFixture.getEditor(); PsiFile file = myFixture.getFile(); - Editor completionEditor = InjectedLanguageFacadeImpl.getEditorForInjectedLanguageNoCommit(editor, file); + Editor completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file); PsiElement element = TargetElementUtilBase.findTargetElement(completionEditor, TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED | TargetElementUtilBase.ELEMENT_NAME_ACCEPTED); assert element != null; diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java index 44a430482516..7a137a175f05 100644 --- a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java +++ b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java @@ -323,7 +323,8 @@ public class GitMergeProvider implements MergeProvider2 { for (VirtualFile f : files) { String path = VcsFileUtil.relativePath(root, f); Conflict c = cs.get(path); - assert c != null : "The conflict not found for the file: " + f.getPath() + "(" + path + ")"; + log.assertTrue(c != null, String.format("The conflict not found for the file: %s(%s)%nFull ls-files output: %n%s", + f.getPath(), path, output)); c.myFile = f; if (c.myStatusTheirs == null) { c.myStatusTheirs = Conflict.Status.DELETED; diff --git a/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/after.groovy.template b/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/after.groovy.template new file mode 100644 index 000000000000..d39ed06ecad8 --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/after.groovy.template @@ -0,0 +1,2 @@ +print '''first + second''' \ No newline at end of file diff --git a/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/before.groovy.template b/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/before.groovy.template new file mode 100644 index 000000000000..588872062d48 --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/before.groovy.template @@ -0,0 +1 @@ +print 'first\n second' \ No newline at end of file diff --git a/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/description.html b/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/description.html new file mode 100644 index 000000000000..5bc803413371 --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/ConvertStringToMultilineIntention/description.html @@ -0,0 +1,5 @@ + + +This intention converts singleline string literal to multiline literal. + + \ No newline at end of file diff --git a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 10c1efcbf01b..093e7182181f 100644 --- a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -1,6 +1,7 @@ package org.jetbrains.jps.incremental.groovy; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; @@ -29,6 +30,7 @@ import java.util.*; * Date: 10/25/11 */ public class GroovyBuilder extends ModuleLevelBuilder { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.groovy.GroovyBuilder"); public static final String BUILDER_NAME = "groovy"; private static final Key CHUNK_REBUILD_ORDERED = Key.create("CHUNK_REBUILD_ORDERED"); private final boolean myForStubs; @@ -47,6 +49,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { public ModuleLevelBuilder.ExitCode build(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { try { final List toCompile = collectChangedFiles(context, chunk); + LOG.info((myForStubs ? "stubs" : "groovyc") + ", toCompile=" + toCompile); if (toCompile.isEmpty()) { return ExitCode.NOTHING_DONE; } @@ -92,6 +95,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { CHUNK_REBUILD_ORDERED.set(context, null); } else { CHUNK_REBUILD_ORDERED.set(context, Boolean.TRUE); + LOG.info("Order chunk rebuild"); return ExitCode.CHUNK_REBUILD_REQUIRED; } } @@ -104,12 +108,14 @@ public class GroovyBuilder extends ModuleLevelBuilder { } for (CompilerMessage message : handler.getCompilerMessages()) { + LOG.info(message.toString()); context.processMessage(message); } List compiled = new ArrayList(); for (GroovycOSProcessHandler.OutputItem item : handler.getSuccessfullyCompiled()) { + LOG.info("Compiled " + item); compiled.add(ensureCorrectOutput(context, chunk, item, generationOutputs, compilerOutput)); } diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 65d5a32f4603..84ec2b08e529 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -1106,6 +1106,11 @@ intention.category.groovy/intention.category.conversions org.jetbrains.plugins.groovy.intentions.conversions.ConvertMethodToClosureIntention + + org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle + intention.category.groovy/intention.category.conversions + org.jetbrains.plugins.groovy.intentions.conversions.ConvertStringToMultilineIntention + org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle intention.category.groovy/intention.category.conversions diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index 21fc4b593aaa..440dd72eb7aa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -124,6 +124,7 @@ import.class=Import Class create.class.family.name=Create Class create.class.text=Create Class {0} create.interface.text=Create Interface {0} +create.annotation.text=Create Annotation {0} static.declaration.in.inner.class=Inner classes cannot have static declarations constructors.are.not.allowed.in.anonymous.class=Constructors are not allowed in anonymous class no.such.property=Property ''{0}'' does not exist diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 8de676cd4da2..5ae9c3c6b8ae 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; import com.intellij.codeInsight.daemon.impl.quickfix.AddMethodBodyFix; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind; import com.intellij.codeInsight.daemon.impl.quickfix.CreateConstructorMatchingSuperFix; import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix; import com.intellij.codeInsight.generation.OverrideImplementUtil; @@ -165,8 +166,8 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { annotation.setTextAttributes(DefaultHighlighter.METHOD_DECLARATION); } } - else if (parent instanceof PsiField) { - final boolean isStatic = ((PsiField)parent).hasModifierProperty(PsiModifier.STATIC); + else if (parent instanceof PsiField || parent instanceof GrVariable && ResolveUtil.isScriptField((GrVariable)parent)) { + final boolean isStatic = ((PsiVariable)parent).hasModifierProperty(PsiModifier.STATIC); final Annotation annotation = holder.createInfoAnnotation(element, null); annotation.setTextAttributes(isStatic ? DefaultHighlighter.STATIC_FIELD : DefaultHighlighter.INSTANCE_FIELD); } @@ -185,8 +186,8 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { private static void highlightResolved(AnnotationHolder holder, GrReferenceElement refElement, PsiElement resolved) { final PsiElement refNameElement = getElementToHighlight(refElement); - if (resolved instanceof PsiField) { - boolean isStatic = ((PsiField)resolved).hasModifierProperty(PsiModifier.STATIC); + if (resolved instanceof PsiField || resolved instanceof GrVariable && ResolveUtil.isScriptField((GrVariable)resolved)) { + boolean isStatic = ((PsiVariable)resolved).hasModifierProperty(PsiModifier.STATIC); Annotation annotation = holder.createInfoAnnotation(refNameElement, null); annotation.setTextAttributes(isStatic ? DefaultHighlighter.STATIC_FIELD : DefaultHighlighter.INSTANCE_FIELD); } @@ -1981,21 +1982,29 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } else { if (shouldBeInterface(refElement)) { - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.INTERFACE)); + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE)); } else if (shouldBeClass(refElement)) { - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.CLASS)); - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.ENUM)); + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS)); + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM)); + } + else if (shouldBeAnnotation(refElement)) { + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION)); } else { - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.CLASS)); - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.INTERFACE)); - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.ENUM)); + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS)); + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE)); + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM)); + annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION)); } } } } + private static boolean shouldBeAnnotation(GrReferenceElement element) { + return element.getParent() instanceof GrAnnotation; + } + private static boolean shouldBeInterface(GrReferenceElement myRefElement) { PsiElement parent = myRefElement.getParent(); return parent instanceof GrImplementsClause || parent instanceof GrExtendsClause && parent.getParent() instanceof GrInterfaceDefinition; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/KeywordHighlighter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/KeywordHighlighter.java index 600c86638322..9ee5fbf48d10 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/KeywordHighlighter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/KeywordHighlighter.java @@ -81,14 +81,13 @@ public class KeywordHighlighter extends TextEditorHighlightingPass { return; //don't highlight foo.def } - result.add(HighlightInfo.createHighlightInfo(HighlightInfoType.INFORMATION, element, null, DefaultHighlighter.KEYWORD_ATTRIBUTES)); + result.add(HighlightInfo.createHighlightInfo(HighlightInfoType.INFORMATION, element, null, DefaultHighlighter.KEYWORD)); } @Override public void doApplyInformationToEditor() { if (toHighlight == null) return; - UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), toHighlight, getColorsScheme(), - getId()); + UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), toHighlight, getColorsScheme(), getId()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java index 07822de94efb..0c341df41ece 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java @@ -16,7 +16,9 @@ package org.jetbrains.plugins.groovy.annotator.intentions; + import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.intention.impl.CreateClassDialog; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.WriteAction; @@ -24,7 +26,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -40,12 +44,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini * @author ilyas */ public abstract class CreateClassActionBase implements IntentionAction { - private Type myType; + private CreateClassKind myType; protected final GrReferenceElement myRefElement; private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.annotator.intentions.CreateClassActionBase"); - public CreateClassActionBase(Type type, GrReferenceElement refElement) { + public CreateClassActionBase(CreateClassKind type, GrReferenceElement refElement) { myType = type; myRefElement = refElement; } @@ -60,6 +64,8 @@ public abstract class CreateClassActionBase implements IntentionAction { return GroovyBundle.message("create.class.text", referenceName); case INTERFACE: return GroovyBundle.message("create.interface.text", referenceName); + case ANNOTATION: + return GroovyBundle.message("create.annotation.text", referenceName); default: return ""; } @@ -75,11 +81,11 @@ public abstract class CreateClassActionBase implements IntentionAction { } public boolean startInWriteAction() { - return true; + return false; } - protected Type getType() { + protected CreateClassKind getType() { return myType; } @@ -145,7 +151,17 @@ public abstract class CreateClassActionBase implements IntentionAction { } } - public static enum Type { - ENUM, CLASS, INTERFACE + @Nullable + protected PsiDirectory getTargetDirectory(Project project, String qualifier, String name, Module module, String title) { + CreateClassDialog dialog = new CreateClassDialog(project, title, name, qualifier, getType(), false, module) { + @Override + protected boolean reportBaseInSourceSelectionInTest() { + return true; + } + }; + dialog.show(); + if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null; + + return dialog.getTargetDirectory(); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java index c7a44098fe4b..e8ee8f9e0a2e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java @@ -16,12 +16,15 @@ package org.jetbrains.plugins.groovy.annotator.intentions; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; @@ -34,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; @@ -49,58 +51,91 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; public abstract class CreateClassFix { public static IntentionAction createClassFromNewAction(final GrNewExpression expression) { - return new CreateClassActionBase(CreateClassActionBase.Type.CLASS, expression.getReferenceElement()) { + return new CreateClassActionBase(CreateClassKind.CLASS, expression.getReferenceElement()) { public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { if (!(file instanceof GroovyFileBase)) return; - GroovyFileBase groovyFile = (GroovyFileBase) file; - final String qualifier = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : ""; + GroovyFileBase groovyFile = (GroovyFileBase)file; final PsiManager manager = myRefElement.getManager(); - final String name = myRefElement.getReferenceName(); - assert name != null; - final Module module = ModuleUtil.findModuleForPsiElement(file); + + final String qualifier; + final String name; + final Module module; + final AccessToken accessToken = ReadAction.start(); + try { + qualifier = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : ""; + name = myRefElement.getReferenceName(); + assert name != null; + module = ModuleUtil.findModuleForPsiElement(file); + } + finally { + accessToken.finish(); + } + PsiDirectory targetDirectory = getTargetDirectory(project, qualifier, name, module, getText()); if (targetDirectory == null) return; GrTypeDefinition targetClass = createClassByType(targetDirectory, name, manager, myRefElement, NewGroovyClassAction.GROOVY_CLASS); + if (targetClass == null) return; - GrArgumentList argList = expression.getArgumentList(); - if (argList != null && argList.getNamedArguments().length + argList.getExpressionArguments().length > 0 && targetClass != null) { - - PsiType[] argTypes = PsiUtil.getArgumentTypes(myRefElement, false); - assert argTypes != null; - - ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length]; - String[] paramTypes = new String[argTypes.length]; - String[] paramNames = new String[argTypes.length]; - - for (int i = 0; i < argTypes.length; i++) { - PsiType argType = argTypes[i]; - if (argType == null) argType = TypesUtil.getJavaLangObject(myRefElement); - paramTypes[i] = "Object"; - paramNames[i] = "o" + i; - paramTypesExpressions[i] = new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, myRefElement.getManager()); - } - - GrMethod method = GroovyPsiElementFactory.getInstance(project).createConstructorFromText(name, paramTypes, paramNames, "{\n}"); - method = targetClass.addMemberDeclaration(method, null); - final PsiNameIdentifierOwner context = PsiTreeUtil.getParentOfType(myRefElement, PsiMethod.class, PsiClass.class); - IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true, context); - } else { + PsiType[] argTypes = getArgTypes(myRefElement); + if (argTypes != null) { + generateConstructor(myRefElement, name, argTypes, targetClass, project); + } + else { putCursor(project, targetClass.getContainingFile(), targetClass); } addImportForClass(groovyFile, qualifier, targetClass); } - }; } - public static IntentionAction createClassFixAction(final GrReferenceElement refElement, CreateClassActionBase.Type type) { - return new CreateClassActionBase(type, refElement) { + @Nullable + private static PsiType[] getArgTypes(GrReferenceElement refElement) { + final AccessToken accessToken = ReadAction.start(); + try { + return PsiUtil.getArgumentTypes(refElement, false); + } + finally { + accessToken.finish(); + } + } + private static void generateConstructor(@NotNull PsiElement refElement, + @NotNull String name, + @NotNull PsiType[] argTypes, + @NotNull GrTypeDefinition targetClass, + @NotNull Project project) { + final AccessToken writeLock = WriteAction.start(); + try { + ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length]; + String[] paramTypes = new String[argTypes.length]; + String[] paramNames = new String[argTypes.length]; + + for (int i = 0; i < argTypes.length; i++) { + PsiType argType = argTypes[i]; + if (argType == null) argType = TypesUtil.getJavaLangObject(refElement); + paramTypes[i] = "Object"; + paramNames[i] = "o" + i; + paramTypesExpressions[i] = new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, refElement.getManager()); + } + + GrMethod method = GroovyPsiElementFactory.getInstance(project).createConstructorFromText(name, paramTypes, paramNames, "{\n}"); + + method = targetClass.addMemberDeclaration(method, null); + final PsiNameIdentifierOwner context = PsiTreeUtil.getParentOfType(refElement, PsiMethod.class, PsiClass.class); + IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true, context); + } + finally { + writeLock.finish(); + } + } + + public static IntentionAction createClassFixAction(final GrReferenceElement refElement, CreateClassKind type) { + return new CreateClassActionBase(type, refElement) { public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { if (!(file instanceof GroovyFileBase)) return; - GroovyFileBase groovyFile = (GroovyFileBase) file; + GroovyFileBase groovyFile = (GroovyFileBase)file; final String qualifier = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : ""; final PsiManager manager = PsiManager.getInstance(project); final String name = myRefElement.getReferenceName(); @@ -109,18 +144,7 @@ public abstract class CreateClassFix { if (targetDirectory == null) return; - String templateName = null; - switch (getType()) { - case ENUM: - templateName = NewGroovyClassAction.GROOVY_ENUM; - break; - case CLASS: - templateName = NewGroovyClassAction.GROOVY_CLASS; - break; - case INTERFACE: - templateName = NewGroovyClassAction.GROOVY_INTERFACE; - break; - } + String templateName = getTemplateName(getType()); assert name != null; PsiClass targetClass = createClassByType(targetDirectory, name, manager, myRefElement, templateName); if (targetClass != null) { @@ -128,29 +152,39 @@ public abstract class CreateClassFix { putCursor(project, targetClass.getContainingFile(), targetClass); } } - }; } - @Nullable - private static PsiDirectory getTargetDirectory(Project project, String qualifier, String name, Module module, String title) { - GroovyCreateClassDialog dialog = new GroovyCreateClassDialog(project, title, name, qualifier, module); - dialog.show(); - if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null; - return dialog.getTargetDirectory(); + private static String getTemplateName(CreateClassKind createClassKind) { + switch (createClassKind) { + case ENUM: + return NewGroovyClassAction.GROOVY_ENUM; + case CLASS: + return NewGroovyClassAction.GROOVY_CLASS; + case INTERFACE: + return NewGroovyClassAction.GROOVY_INTERFACE; + case ANNOTATION: + return NewGroovyClassAction.GROOVY_ANNOTATION; + default: + return null; + } } - protected static void addImportForClass(GroovyFileBase groovyFile, String qualifier, PsiClass targetClass) throws IncorrectOperationException { - if (targetClass != null) { - // add import for created class - String qualifiedName = targetClass.getQualifiedName(); - if (qualifiedName != null && qualifiedName.contains(".")) { - String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf(".")); - if (!packageName.equals(qualifier)) { + protected static void addImportForClass(@NotNull GroovyFileBase groovyFile, @NotNull String qualifier, @NotNull PsiClass targetClass) + throws IncorrectOperationException { + // add import for created class + String qualifiedName = targetClass.getQualifiedName(); + if (qualifiedName != null && qualifiedName.contains(".")) { + String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf(".")); + if (!packageName.equals(qualifier)) { + final AccessToken accessToken = WriteAction.start(); + try { groovyFile.addImportForClass(targetClass); } + finally { + accessToken.finish(); + } } } } - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java index 0fd40f40a421..39629d585163 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java @@ -119,8 +119,8 @@ public class UnnecessaryQualifiedReferenceInspection extends BaseInspection { @Override protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement startElement = descriptor.getStartElement(); - LOG.assertTrue(startElement instanceof GrReferenceElement); - GrReferenceAdjuster.shortenReference((GrQualifiedReference)startElement); + LOG.assertTrue(startElement instanceof GrReferenceElement); + GrReferenceAdjuster.shortenReference((GrQualifiedReference)startElement); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index 41a0e471bd6c..6bcd52cb3ec8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -81,6 +81,8 @@ convert.closure.to.method.intention.name=Convert to method convert.closure.to.method.intention.family.name=Convert property to method convert.method.to.closure.intention.name=Convert to property convert.method.to.closure.intention.family.name=Convert method to property of closure type +convert.string.to.multiline.intention.name=Convert to Multiline +convert.string.to.multiline.intention.family.name=Convert literal to multiline literal convert.junit.assertion.to.assert.statement.intention.name=Convert JUnit assertion to assert statement convert.junit.assertion.to.assert.statement.intention.family.name=Convert JUnit assertion to assert statement ########################################################################################################### diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertStringToMultilineIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertStringToMultilineIntention.java new file mode 100644 index 000000000000..62b5b8d43e03 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertStringToMultilineIntention.java @@ -0,0 +1,135 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.intentions.conversions; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.intentions.base.Intention; +import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; +import org.jetbrains.plugins.groovy.lang.editor.actions.GroovyEditorActionUtil; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrStringImpl; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; + +/** + * @author Max Medvedev + */ +public class ConvertStringToMultilineIntention extends Intention { + private static final Logger LOG = Logger.getInstance(ConvertStringToMultilineIntention.class); + + public static final String hint = "Convert to Multiline"; + + @Override + protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException { + String quote = element.getText().startsWith("'") ? "'''" : "\"\"\""; + + StringBuilder buffer = new StringBuilder(); + buffer.append(quote); + + GrExpression old; + + if (element instanceof GrLiteralImpl) { + appendSimpleStringValue(element, buffer, quote); + old = (GrExpression)element; + } + else { + final GrStringImpl gstring = PsiTreeUtil.getParentOfType(element, GrStringImpl.class); + for (ASTNode child = gstring.getNode().getFirstChildNode(); child != null; child = child.getTreeNext()) { + if (child.getElementType() == GroovyTokenTypes.mGSTRING_CONTENT) { + appendGStringContent(child, buffer); + } + else if (child.getElementType() == GroovyElementTypes.GSTRING_INJECTION) { + buffer.append(child.getText()); + } + } + old = gstring; + } + + buffer.append(quote); + try { + final GrExpression newLiteral = GroovyPsiElementFactory.getInstance(project).createExpressionFromText(buffer.toString()); + old.replaceWithExpression(newLiteral, true); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + + private static void appendGStringContent(ASTNode child, StringBuilder buffer) { + final String text = child.getText(); + final StringBuilder parsed = new StringBuilder(); + if (GrStringUtil.parseStringCharacters(text, parsed, null)) { + buffer.append(parsed); + } + else { + buffer.append(text); + } + } + + private static void appendSimpleStringValue(PsiElement element, StringBuilder buffer, String quote) { + final Object value = ((GrLiteralImpl)element).getValue(); + if (value instanceof String) { + if ("'''".equals(quote)) { + GrStringUtil.escapeStringCharacters(((String)value).length(), (String)value, "", false, true, buffer); + } + else { + GrStringUtil.escapeSymbolsForGString((CharSequence)value, false, false, buffer); + } + } + else { + buffer.append(GrStringUtil.removeQuotes(element.getText())); + } + } + + @NotNull + @Override + protected PsiElementPredicate getElementPredicate() { + return new PsiElementPredicate() { + @Override + public boolean satisfiedBy(PsiElement element) { + if (element instanceof GrLiteralImpl) { + final ASTNode node = element.getFirstChild().getNode(); + final IElementType type = node.getElementType(); + if (type == GroovyTokenTypes.mSTRING_LITERAL) { + return GroovyEditorActionUtil.isPlainStringLiteral(node); + } + if (type == GroovyTokenTypes.mGSTRING_LITERAL) { + return GroovyEditorActionUtil.isPlainGString(node); + } + } + else { + final GrStringImpl gstring = PsiTreeUtil.getParentOfType(element, GrStringImpl.class, false, GrMember.class, GroovyFile.class); + if (gstring == null) return false; + return gstring.isPlainString(); + } + return false; + } + }; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportOnDemandIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportOnDemandIntention.java index 320b1b6d0918..d52f269a2fee 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportOnDemandIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportOnDemandIntention.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.intentions.style; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; @@ -39,8 +38,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem * @author Maxim.Medvedev */ public class ImportOnDemandIntention extends Intention { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.intentions.style.ImportOnDemandIntention"); - @Override protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException { @@ -62,8 +59,8 @@ public class ImportOnDemandIntention extends Intention { final PsiElement refElement = reference.getElement(); if (refElement == null) continue; final PsiElement parent = refElement.getParent(); - if (parent instanceof GrQualifiedReference) { - GrReferenceAdjuster.shortenReference((GrQualifiedReference)parent); + if (parent instanceof GrQualifiedReference) { + GrReferenceAdjuster.shortenReference((GrQualifiedReference)parent); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportStaticIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportStaticIntention.java index 36ceb3948420..733fcd1c1758 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportStaticIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ImportStaticIntention.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.intentions.style; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -31,31 +30,39 @@ import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList; /** * @author Maxim.Medvedev */ public class ImportStaticIntention extends Intention { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.intentions.style.ImportStaticIntention"); private static final Key TEMP_REFERENT_USER_DATA = new Key("TEMP_REFERENT_USER_DATA"); @Override - protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException { + protected void processIntention(@NotNull PsiElement element, final Project project, final Editor editor) + throws IncorrectOperationException { + final PsiElement resolved; + final String name; + final GroovyFile file; + final GrImportStatement importStatement; + boolean isAnythingShortened; if (!(element instanceof GrReferenceExpression)) return; final GrReferenceExpression ref = (GrReferenceExpression)element; - final PsiElement resolved = ref.resolve(); + resolved = ref.resolve(); if (!(resolved instanceof PsiMember)) return; final PsiClass containingClass = ((PsiMember)resolved).getContainingClass(); if (containingClass == null) return; final String qname = containingClass.getQualifiedName(); - final String name = ((PsiMember)resolved).getName(); + name = ((PsiMember)resolved).getName(); + if (name == null) return; final PsiFile containingFile = element.getContainingFile(); if (!(containingFile instanceof GroovyFile)) return; - final GroovyFile file = (GroovyFile)containingFile; + file = (GroovyFile)containingFile; file.accept(new GroovyRecursiveElementVisitor() { @Override public void visitReferenceExpression(GrReferenceExpression expression) { @@ -69,27 +76,30 @@ public class ImportStaticIntention extends Intention { } }); - final GrImportStatement importStatement = - GroovyPsiElementFactory.getInstance(project).createImportStatementFromText(qname + "." + name, true, false, null); - - - file.addImport(importStatement); + final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); + final GrImportStatement tempImport = factory.createImportStatementFromText(qname + "." + name, true, false, null); + importStatement = file.addImport(tempImport); + isAnythingShortened = false; for (PsiReference reference : ReferencesSearch.search(resolved, new LocalSearchScope(containingFile))) { final PsiElement refElement = reference.getElement(); - if (refElement instanceof GrQualifiedReference) { - GrReferenceAdjuster.shortenReference((GrQualifiedReference)refElement); + if (refElement instanceof GrQualifiedReference) { + isAnythingShortened |= GrReferenceAdjuster.shortenReference((GrQualifiedReference)refElement); } } + if (!isAnythingShortened) { + importStatement.delete(); + return; + } file.accept(new GroovyRecursiveElementVisitor() { @Override public void visitReferenceExpression(GrReferenceExpression expression) { super.visitReferenceExpression(expression); - if (expression.getTypeArgumentList() != null && - expression.getTypeArgumentList().getFirstChild() != null) { + GrTypeArgumentList typeArgumentList = expression.getTypeArgumentList(); + if (typeArgumentList != null && typeArgumentList.getFirstChild() != null) { expression.putUserData(TEMP_REFERENT_USER_DATA, null); return; @@ -97,8 +107,9 @@ public class ImportStaticIntention extends Intention { if (name.equals(expression.getReferenceName())) { if (expression.isQualified()) { - if (expression.getQualifierExpression() instanceof GrReferenceExpression) { - PsiElement aClass = ((GrReferenceExpression)expression.getQualifierExpression()).resolve(); + GrExpression qualifier = expression.getQualifierExpression(); + if (qualifier instanceof GrReferenceExpression) { + PsiElement aClass = ((GrReferenceExpression)qualifier).resolve(); if (aClass == ((PsiMember)resolved).getContainingClass()) { GrReferenceAdjuster.shortenReference(expression); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GrReferenceAdjuster.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GrReferenceAdjuster.java index 495a74b09476..c47b09bc1261 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GrReferenceAdjuster.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GrReferenceAdjuster.java @@ -41,38 +41,40 @@ public class GrReferenceAdjuster { } - public static void shortenReferences(PsiElement element) { + public static boolean shortenReferences(PsiElement element) { final TextRange range = element.getTextRange(); - shortenReferences(element, range.getStartOffset(), range.getEndOffset(), true, false); + return shortenReferences(element, range.getStartOffset(), range.getEndOffset(), true, false); } - public static void shortenReferences(PsiElement element, int start, int end, boolean addImports, boolean incomplete) { - process(element, start, end, addImports, incomplete); + public static boolean shortenReferences(PsiElement element, int start, int end, boolean addImports, boolean incomplete) { + return process(element, start, end, addImports, incomplete); } - public static void shortenReference(GrQualifiedReference ref) { - shortenReferenceInner(ref, true, false); + public static boolean shortenReference(GrQualifiedReference ref) { + boolean result = shortenReferenceInner(ref, true, false); final TextRange range = ref.getTextRange(); - process(ref, range.getStartOffset(), range.getEndOffset(), true, false); + result |= process(ref, range.getStartOffset(), range.getEndOffset(), true, false); + return result; } - private static void process(PsiElement element, int start, int end, boolean addImports, boolean incomplete) { - if (element instanceof GrQualifiedReference && ((GrQualifiedReference)element).resolve() instanceof PsiClass) { - shortenReferenceInner((GrQualifiedReference)element, addImports, incomplete); + private static boolean process(PsiElement element, int start, int end, boolean addImports, boolean incomplete) { + boolean result = false; + if (element instanceof GrQualifiedReference && ((GrQualifiedReference)element).resolve() instanceof PsiClass) { + result = shortenReferenceInner((GrQualifiedReference)element, addImports, incomplete); } - else if (element instanceof GrReferenceExpression && ((GrReferenceExpression)element).getQualifier() instanceof GrThisSuperReferenceExpression) { - shortenReferenceInner((GrReferenceExpression)element, addImports, incomplete); + result = shortenReferenceInner((GrReferenceExpression)element, addImports, incomplete); } PsiElement child = element.getFirstChild(); while (child != null) { final TextRange range = child.getTextRange(); if (start < range.getEndOffset() && range.getStartOffset() < end) { - process(child, start, end, addImports, incomplete); + result |= process(child, start, end, addImports, incomplete); } child = child.getNextSibling(); } + return result; } private static boolean shortenReferenceInner(GrQualifiedReference ref, boolean addImports, boolean incomplete) { @@ -141,6 +143,7 @@ public class GrReferenceAdjuster { } + @SuppressWarnings("unchecked") private static GrQualifiedReference getCopy(GrQualifiedReference ref) { if (ref.getParent() instanceof GrMethodCall) { final GrMethodCall copy = ((GrMethodCall)ref.getParent().copy()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 50a61e334e7e..72753a189542 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -239,9 +239,9 @@ public class GroovyCompletionContributor extends CompletionContributor { if (CompletionService.getCompletionService().getAdvertisementText() == null && parameters.getInvocationCount() > 0 && CompletionUtil.shouldShowFeature(parameters, JavaCompletionFeatures.GLOBAL_MEMBER_NAME)) { - final String shortcut = getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION); + final String shortcut = getActionShortcut(IdeActions.ACTION_CODE_COMPLETION); if (shortcut != null) { - CompletionService.getCompletionService().setAdvertisementText("Pressing " + shortcut + " without a class qualifier would show all accessible static methods"); + CompletionService.getCompletionService().setAdvertisementText("Pressing " + shortcut + " twice without a class qualifier would show all accessible static methods"); } } @@ -260,19 +260,8 @@ public class GroovyCompletionContributor extends CompletionContributor { // class name stuff - extend(CompletionType.CLASS_NAME, psiElement().withParent(GrReferenceElement.class), new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull final CompletionResultSet result) { - final PsiElement position = parameters.getPosition(); - if (((GrReferenceElement)position.getParent()).getQualifier() != null) return; - - if (StringUtil.isEmpty(result.getPrefixMatcher().getPrefix())) return; - - completeStaticMembers(parameters).processStaticMethodsGlobally(result); - } - }); + extend(CompletionType.CLASS_NAME, psiElement().withParent(GrReferenceElement.class), new GlobalStaticMembersProvider()); + extend(CompletionType.BASIC, psiElement().withParent(GrReferenceElement.class), new GlobalStaticMembersProvider()); extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider() { @Override @@ -784,4 +773,20 @@ public class GroovyCompletionContributor extends CompletionContributor { } } } + + private static class GlobalStaticMembersProvider extends CompletionProvider { + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull final CompletionResultSet result) { + if (!parameters.isExtendedCompletion()) return; + + final PsiElement position = parameters.getPosition(); + if (((GrReferenceElement)position.getParent()).getQualifier() != null) return; + + if (StringUtil.isEmpty(result.getPrefixMatcher().getPrefix())) return; + + completeStaticMembers(parameters).processStaticMethodsGlobally(result); + } + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java index f0817fe51827..2502a7209cd0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java @@ -52,7 +52,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.*; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; @@ -111,11 +110,13 @@ public class GroovyCompletionData { if (isAfterForParameter(position)) { addKeywords(result, true, "in"); } - else if (isInfixOperatorPosition(position)) { + if (isInfixOperatorPosition(position)) { addKeywords(result, true, "in", PsiKeyword.INSTANCEOF); - } else if (suggestThrows(position)) { + } + if (afterAbstractMethod(position)) { result.addElement(keyword(PsiKeyword.THROWS, TailType.INSERT_SPACE)); - } else if (suggestPrimitiveTypes(position)) { + } + if (suggestPrimitiveTypes(position)) { boolean inCast = psiElement() .afterLeaf(psiElement().withText("(").withParent(psiElement(GrParenthesizedExpression.class, GrTypeCastExpression.class))) .accepts(position); @@ -262,7 +263,8 @@ public class GroovyCompletionData { public static void addGroovyDocKeywords(CompletionParameters parameters, CompletionResultSet result) { PsiElement position = parameters.getPosition(); - if (PlatformPatterns.psiElement(GroovyDocTokenTypes.mGDOC_TAG_NAME).andNot(PlatformPatterns.psiElement().afterLeaf(".")).accepts(position)) { + if (PlatformPatterns.psiElement(GroovyDocTokenTypes.mGDOC_TAG_NAME).andNot(PlatformPatterns.psiElement().afterLeaf(".")).accepts( + position)) { String[] tags = position.getParent() instanceof GrDocInlinedTag ? INLINED_DOC_TAGS : DOC_TAGS; for (String docTag : tags) { result.addElement(TailTypeDecorator.withTail(LookupElementBuilder.create(docTag), TailType.INSERT_SPACE)); @@ -320,7 +322,9 @@ public class GroovyCompletionData { } public static boolean suggestClassInterfaceEnum(PsiElement context) { - if (suggestThrows(context) || addExtendsImplements(context).length > 0) { + PsiElement nextNonSpace = PsiUtil.getNextNonSpace(context); + if (nextNonSpace instanceof PsiErrorElement) nextNonSpace = PsiUtil.getNextNonSpace(nextNonSpace); + if (afterAbstractMethod(context) && nextNonSpace != null && nextNonSpace.getText().startsWith("{") || addExtendsImplements(context).length > 0) { return false; } @@ -485,7 +489,7 @@ public class GroovyCompletionData { return false; } - private static boolean suggestThrows(PsiElement context) { + private static boolean afterAbstractMethod(PsiElement context) { PsiElement candidate = null; if (GroovyCompletionUtil.isInTypeDefinitionBody(context)) { PsiElement run = context; @@ -493,7 +497,8 @@ public class GroovyCompletionData { run = run.getParent(); assert run != null; } - candidate = PsiTreeUtil.getPrevSiblingOfType(run, GrMember.class); + candidate = PsiUtil.skipWhitespaces(run.getPrevSibling(), false); + if (candidate instanceof PsiErrorElement) candidate = candidate.getPrevSibling(); } else if (context.getParent() instanceof PsiErrorElement) { candidate = context.getParent().getPrevSibling(); @@ -503,6 +508,9 @@ public class GroovyCompletionData { } private static boolean suggestPrimitiveTypes(PsiElement context) { + if (isInfixOperatorPosition(context)) return false; + if (isAfterForParameter(context)) return false; + final PsiElement parent = context.getParent(); if (parent == null) return false; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java index 470950fea483..143f1518ff4f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/handlers/AfterNewClassInsertHandler.java @@ -73,6 +73,8 @@ public class AfterNewClassInsertHandler implements InsertHandler result = new ArrayList(); for (PsiElement child : getChildren()) { @@ -511,12 +504,20 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { CodeStyleManager styleManager = CodeStyleManager.getInstance(getManager().getProject()); PsiElement parent = result.getContainingFile(); TextRange range = result.getTextRange(); - styleManager.reformatRange(parent, range.getEndOffset() - 1, range.getEndOffset() + 1); - styleManager.reformatRange(parent, range.getStartOffset() - 1, range.getStartOffset() + 1); + if (checkRange(parent, range.getEndOffset())) { + styleManager.reformatRange(parent, range.getEndOffset() - 1, range.getEndOffset() + 1); + } + if (checkRange(parent, range.getStartOffset())) { + styleManager.reformatRange(parent, range.getStartOffset() - 1, range.getStartOffset() + 1); + } return result; } + private static boolean checkRange(PsiElement parent, int offset) { + return parent.getTextRange().contains(offset -1) && parent.getTextRange().contains(offset+1); + } + public void removeMemberDeclaration(GrMembersDeclaration decl) { try { deleteChildRange(decl, decl); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableImpl.java index ce2527f4bd02..a0e492d7e125 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableImpl.java @@ -17,10 +17,12 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.stubs.StubElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; /** * @author Dmitry.Krasilschikov @@ -39,4 +41,14 @@ public class GrVariableImpl extends GrVariableBaseImpl implements G public String toString() { return "Variable"; } + + @Override + public PsiElement getContext() { + if (ResolveUtil.isScriptField(this)) { + return getContainingFile(); + } + else { + return super.getContext(); + } + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java index 23e962b95722..5265e0d70b92 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java @@ -19,7 +19,9 @@ import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.util.*; import com.intellij.psi.*; import com.intellij.psi.impl.*; -import com.intellij.psi.impl.light.*; +import com.intellij.psi.impl.light.LightElement; +import com.intellij.psi.impl.light.LightMethodBuilder; +import com.intellij.psi.impl.light.LightModifierList; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.scope.BaseScopeProcessor; import com.intellij.psi.scope.PsiScopeProcessor; @@ -32,6 +34,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTopLevelDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; @@ -353,15 +356,14 @@ public class GroovyScriptClass extends LightElement implements GrMemberOwner, Sy @Override public List compute() { final List result = new ArrayList(); - myFile.accept(new PsiRecursiveElementWalkingVisitor() { + myFile.accept(new GroovyRecursiveElementVisitor() { @Override - public void visitElement(PsiElement element) { - if (element instanceof GrVariableDeclaration && - ((GrVariableDeclaration)element).getModifierList().findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD) != null) { - Collections.addAll(result, ((GrVariableDeclaration)element).getVariables()); + public void visitVariableDeclaration(GrVariableDeclaration element) { + if (element.getModifierList().findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD) != null) { + Collections.addAll(result, element.getVariables()); } - super.visitElement(element); + super.visitVariableDeclaration(element); } }); return result; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java index 7e942d05510d..8def3caf30ad 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java @@ -248,7 +248,7 @@ public class GrStringUtil { return b.toString(); } - private static void escapeSymbolsForGString(CharSequence s, boolean isSingleLine, boolean forInjection, StringBuilder b) { + public static void escapeSymbolsForGString(CharSequence s, boolean isSingleLine, boolean forInjection, StringBuilder b) { escapeStringCharacters(s.length(), s, isSingleLine ? "$\"" : "$", isSingleLine, true, b); if (!forInjection) { unescapeCharacters(b, isSingleLine ? "'" : "'\"", true); @@ -828,4 +828,28 @@ public class GrStringUtil { return false; } + + public static void getOperandText(@NotNull GrLiteral operand, @NotNull StringBuilder builder) { + if (operand instanceof GrRegex) { + StringBuilder b = new StringBuilder(); + parseRegexCharacters(removeQuotes(operand.getText()), b, null, operand.getText().startsWith("/")); + escapeSymbolsForGString(b, false, false); + } + else if (operand instanceof GrString) { + builder.append(removeQuotes(operand.getText())); + } + else { + Object value = operand.getValue(); + if (value == null) { + value = removeQuotes(operand.getText()); + } + + String text = value.toString(); + StringBuilder buffer = new StringBuilder(text.length()); + boolean containsLineFeeds = text.indexOf('\n') >= 0 || text.indexOf('\r') >= 0; + escapeStringCharacters(text.length(), text, "$", false, true, buffer); + unescapeCharacters(buffer, containsLineFeeds?"'\"":"'", containsLineFeeds); + builder.append(buffer); + } + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 7f5c771938c8..05b52822d5c9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -828,6 +828,7 @@ public class PsiUtil { return place == clazz; } + @Nullable public static PsiElement skipWhitespaces(@Nullable PsiElement elem, boolean forward) { //noinspection ConstantConditions diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java index 97df07eb5752..f7d20e620d80 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java @@ -37,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; @@ -56,6 +57,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; @@ -64,6 +66,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getContextClass; import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getSmartReturnType; /** @@ -697,4 +700,12 @@ public class ResolveUtil { if (aClass == null) return false; return qName.equals(aClass.getQualifiedName()); } + + public static boolean isScriptField(GrVariable var) { + PsiClass context = getContextClass(var.getParent()); + final GrModifierList modifierList = var.getModifierList(); + return context instanceof GroovyScriptClass && + modifierList != null && + modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD) != null; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java index 30b92f2e5f2e..307b16663143 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java @@ -20,7 +20,6 @@ import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster; -import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; @@ -151,7 +150,7 @@ public class GrIntroduceConstantHandler extends GrIntroduceHandlerBase errors = new ArrayList(); - if (myCurrentMethodRadioButton.isSelected() && myDeclareFinalCheckBox.isSelected() && !!isInvokedInAlwaysInvokedConstructor) { + if (myCurrentMethodRadioButton.isSelected() && myDeclareFinalCheckBox.isSelected() && !isInvokedInAlwaysInvokedConstructor) { errors.add(GroovyRefactoringBundle.message("final.field.cant.be.initialized.in.cur.method")); } if (myDeclareFinalCheckBox.isSelected() && myReplaceAllOccurrencesCheckBox.isSelected() && myInvokedOnLocalVar != null && hasLHSUsages) { @@ -202,11 +207,20 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce visibility.add(myPublicRadioButton); visibility.add(myPropertyRadioButton); - myPrivateRadioButton.setSelected(true); + if (myContext.getScope() instanceof GroovyScriptClass) { + myPropertyRadioButton.setSelected(true); + myPrivateRadioButton.setEnabled(false); + myProtectedRadioButton.setEnabled(false); + myPublicRadioButton.setEnabled(false); + myPropertyRadioButton.setEnabled(false); + } + else { + myPrivateRadioButton.setSelected(true); + } new RadioUpDownListener(myPrivateRadioButton, myProtectedRadioButton, myPublicRadioButton, myPropertyRadioButton); } - private static boolean isAlwaysInvokedConstructor(PsiMethod method, GrTypeDefinition clazz) { + private static boolean isAlwaysInvokedConstructor(PsiMethod method, PsiClass clazz) { if (method == null) return false; if (!method.isConstructor()) return false; final PsiMethod[] constructors = clazz.getConstructors(); @@ -222,12 +236,12 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce return true; } - private static boolean allOccurrencesInOneMethod(PsiElement[] occurrences, GrTypeDefinition clazz) { + private static boolean allOccurrencesInOneMethod(PsiElement[] occurrences, PsiElement scope) { if (occurrences.length == 0) return true; - GrMethod method = GrIntroduceFieldHandler.getContainingMethod(occurrences[0], clazz); + GrMethod method = GrIntroduceFieldHandler.getContainingMethod(occurrences[0], scope); if (method == null) return false; for (int i = 1; i < occurrences.length; i++) { - GrMethod other = GrIntroduceFieldHandler.getContainingMethod(occurrences[i], clazz); + GrMethod other = GrIntroduceFieldHandler.getContainingMethod(occurrences[i], scope); if (other != method) return false; } return true; @@ -335,7 +349,7 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce return null; } - private static boolean canBeInitializedOutsideBlock(@Nullable GrExpression expression, final GrTypeDefinition scope) { + private static boolean canBeInitializedOutsideBlock(@Nullable GrExpression expression, final PsiClass clazz) { if (expression == null) return false; expression = (GrExpression)PsiUtil.skipParentheses(expression, false); if (expression == null) return false; @@ -356,7 +370,7 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce super.visitReferenceExpression(refExpr); final PsiElement resolved = refExpr.resolve(); if (!(resolved instanceof GrVariable)) return; - if (resolved instanceof GrField && scope.getManager().areElementsEquivalent(scope, ((GrField)resolved).getContainingClass())) { + if (resolved instanceof GrField && clazz.getManager().areElementsEquivalent(clazz, ((GrField)resolved).getContainingClass())) { return; } if (resolved instanceof PsiParameter && @@ -375,7 +389,7 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce @Override protected void doOKAction() { - final GrTypeDefinition clazz = (GrTypeDefinition)myContext.getScope(); + final PsiClass clazz = (PsiClass)myContext.getScope(); final String name = getName(); String message = RefactoringBundle.message("field.exists", name, clazz.getQualifiedName()); if (clazz.findFieldByName(name, true) != null && diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java index cd0be459b1ed..cff435a249f1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java @@ -21,11 +21,14 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster; import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; @@ -39,6 +42,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEn import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; @@ -51,6 +56,7 @@ import java.util.ArrayList; import java.util.List; import static com.intellij.util.ArrayUtil.EMPTY_STRING_ARRAY; +import static com.intellij.util.ArrayUtil.getFirstElement; import static org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldSettings.Init.*; /** @@ -71,11 +77,23 @@ public class GrIntroduceFieldHandler extends GrIntroduceHandlerBase filtered = new ArrayList(); for (PsiElement occurrence : occurrences) { - if (!shouldBeStatic(occurrence, clazz)) { + if (!shouldBeStatic(occurrence, scope)) { filtered.add(occurrence); } } return ContainerUtil.toArray(filtered, new PsiElement[filtered.size()]); } - private static void initializeInMethod(GrIntroduceContext context, GrIntroduceFieldSettings settings, GrField field) { + private static void initializeInMethod(GrIntroduceContext context, GrIntroduceFieldSettings settings, GrVariable field) { if (context.getExpression() == null) return; final GrExpression expression = context.getExpression(); - final GrTypeDefinition scope = (GrTypeDefinition)context.getScope(); + final PsiElement _scope = context.getScope(); + final PsiElement scope = _scope instanceof GroovyScriptClass? _scope.getContainingFile(): _scope; final GrMethod method = getContainingMethod(expression, scope); LOG.assertTrue(method != null); @@ -195,12 +229,12 @@ public class GrIntroduceFieldHandler extends GrIntroduceHandlerBase) { + GrReferenceAdjuster.shortenReference((GrQualifiedReference)replaced); } } - private static GrReferenceExpression createRefExpression(GrField field, PsiElement place) { - final PsiClass containingClass = field.getContainingClass(); - LOG.assertTrue(containingClass != null); + private static GrReferenceExpression createRefExpression(GrVariable field, PsiElement place, PsiClass containingClass) { final String qname = containingClass.getQualifiedName(); final String prefix = qname != null ? qname + "." : ""; final String refText; @@ -325,39 +357,43 @@ public class GrIntroduceFieldHandler extends GrIntroduceHandlerBase modifiers = new ArrayList(); + if (context.getScope() instanceof GroovyScriptClass) modifiers.add("@"+GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD); + if (settings.isStatic()) modifiers.add(PsiModifier.STATIC); + if (!PsiModifier.PACKAGE_LOCAL.equals(modifier)) modifiers.add(modifier); + if (settings.declareFinal()) modifiers.add(PsiModifier.FINAL); - fieldDeclaration.getModifierList().setModifierProperty(modifier, true); - if (settings.isStatic()) { - fieldDeclaration.getModifierList().setModifierProperty(PsiModifier.STATIC, true); + final String[] arr_modifiers = ArrayUtil.toStringArray(modifiers); + final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject()); + if (context.getScope() instanceof GroovyScriptClass) { + return factory.createVariableDeclaration(arr_modifiers, initializer, type, name); } - if (settings.declareFinal()) { - fieldDeclaration.getModifierList().setModifierProperty(PsiModifier.FINAL, true); + else { + return factory.createFieldDeclaration(arr_modifiers, name, initializer, type); } - return fieldDeclaration; } @Nullable - static GrMethod getContainingMethod(PsiElement place, GrTypeDefinition clazz) { - while (place != null && place != clazz) { + static GrMethod getContainingMethod(PsiElement place, PsiElement scope) { + while (place != null && place != scope) { place = place.getParent(); if (place instanceof GrMethod) return (GrMethod)place; } return null; } - @NotNull - static GrMember getContainer(PsiElement place, GrTypeDefinition clazz) { + @Nullable + static GrMember getContainer(PsiElement place, PsiElement clazz) { while (place != null && place != clazz) { place = place.getParent(); if (place instanceof GrMember) return (GrMember)place; } - LOG.error("container cannot be null"); return null; } - static boolean shouldBeStatic(PsiElement expr, GrTypeDefinition clazz) { + static boolean shouldBeStatic(PsiElement expr, PsiElement clazz) { final GrMember method = getContainer(expr, clazz); + if (method == null) return false; return method.hasModifierProperty(PsiModifier.STATIC); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy similarity index 62% rename from plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java rename to plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy index ccdaaae4ed02..96539cf63866 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy @@ -16,19 +16,21 @@ package org.jetbrains.plugins.groovy; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.openapi.roots.ModifiableRootModel; -import com.intellij.openapi.roots.OrderRootType; -import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.testFramework.LightProjectDescriptor; -import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.util.TestUtils; + +import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.ContentEntry +import com.intellij.openapi.roots.ModifiableRootModel +import com.intellij.openapi.roots.OrderRootType +import com.intellij.openapi.roots.libraries.Library +import com.intellij.openapi.vfs.JarFileSystem +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.annotations.NonNls +import org.jetbrains.annotations.NotNull + +import static org.jetbrains.plugins.groovy.util.TestUtils.getMockGroovy1_8LibraryName /** * @author peter @@ -37,9 +39,9 @@ public abstract class LightGroovyTestCase extends LightCodeInsightFixtureTestCas public static final LightProjectDescriptor GROOVY_DESCRIPTOR = new DefaultLightProjectDescriptor() { @Override public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) { - final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY").getModifiableModel(); - final VirtualFile groovyJar = - JarFileSystem.getInstance().refreshAndFindFileByPath(TestUtils.getMockGroovy1_8LibraryName()+"!/"); + final Library.ModifiableModel modifiableModel = model.moduleLibraryTable.createLibrary("GROOVY").modifiableModel; + final VirtualFile groovyJar = JarFileSystem.instance.refreshAndFindFileByPath("$mockGroovy1_8LibraryName!/"); + assert groovyJar != null; modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES); modifiableModel.commit(); } @@ -61,4 +63,9 @@ public abstract class LightGroovyTestCase extends LightCodeInsightFixtureTestCas @NonNls protected abstract String getBasePath(); + + protected void addGroovyTransformField() { + myFixture.addClass('''package groovy.transform; public @interface Field{}'''); + } + } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy index 03d25ca15a1c..e82a37460234 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy @@ -20,15 +20,17 @@ package org.jetbrains.plugins.groovy.compiler; import com.intellij.compiler.CompileServerManager import com.intellij.compiler.CompilerConfiguration import com.intellij.compiler.CompilerConfigurationImpl +import com.intellij.compiler.server.BuildManager +import com.intellij.openapi.application.PathManager import com.intellij.openapi.compiler.options.ExcludeEntryDescription import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiFile - +import com.intellij.testFramework.TestLoggerFactory import junit.framework.AssertionFailedError -import com.intellij.openapi.roots.ModuleRootModificationUtil /** * @author peter @@ -211,18 +213,51 @@ public abstract class GroovyCompilerTest extends GroovyCompilerTestCase { assertOutput("Bar", "239"); } + @Override + void runBare() { + def ideaLog = new File(TestLoggerFactory.testLogDir, "idea.log") + def makeLog = new File(PathManager.systemPath, "compile-server/server.log") + if (ideaLog.exists()) { + FileUtil.delete(ideaLog) + } + if (makeLog.exists()) { + FileUtil.delete(makeLog) + } + + try { + super.runBare() + } + catch (Throwable e) { + if (ideaLog.exists()) { + //println "Idea Log:" + //println ideaLog.text + } + + if (makeLog.exists()) { + println "Server Log:" + println makeLog.text + } + System.out.flush() + + throw e + } + } + public void testMakeInTests() throws Throwable { setupTestSources(); myFixture.addFileToProject("tests/Super.groovy", "class Super {}"); assertEmpty(make()); - myFixture.addFileToProject("tests/Sub.groovy", "class Sub {\n" + - " Super xxx() {}\n" + - " static void main(String[] args) {" + - " println 'hello'" + - " }" + - "}"); - myFixture.addFileToProject("tests/Java.java", "public class Java {}"); + def sub = myFixture.addFileToProject("tests/Sub.groovy", "class Sub {\n" + + " Super xxx() {}\n" + + " static void main(String[] args) {" + + " println 'hello'" + + " }" + + "}"); + + def javaFile = myFixture.addFileToProject("tests/Java.java", "public class Java {}"); + BuildManager.instance.notifyFilesChanged([sub.virtualFile.path, javaFile.virtualFile.path]) + assertEmpty(make()); assertOutput("Sub", "hello"); } @@ -590,11 +625,9 @@ class Main { assert !findClassFile('FooX', dep) } - println '1' println make().join('\n') checkClassFiles() - println '2' println make().join('\n') checkClassFiles() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/CompletionTestBase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/CompletionTestBase.java index 7e6cfad36fd4..1d0fedb0483b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/CompletionTestBase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/CompletionTestBase.java @@ -7,6 +7,7 @@ import com.intellij.codeInsight.lookup.impl.LookupImpl; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiPackage; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; @@ -23,10 +24,10 @@ import java.util.List; */ public abstract class CompletionTestBase extends JavaCodeInsightFixtureTestCase { - protected void doTest() throws Throwable { + protected void doTest() { doTest(""); } - protected void doTest(String directory) throws Throwable { + protected void doTest(String directory) { final List stringList = TestUtils.readInput(getTestDataPath() + "/" + getTestName(true) + ".test"); if (directory.length()!=0) directory += "/"; final String fileName = directory + getTestName(true) + "." + getExtension(); @@ -50,7 +51,7 @@ public abstract class CompletionTestBase extends JavaCodeInsightFixtureTestCase @Override public boolean value(LookupElement lookupElement) { final Object o = lookupElement.getObject(); - return !(o instanceof PsiMember) && !(o instanceof GrVariable) && !(o instanceof GroovyResolveResult); + return !(o instanceof PsiMember) && !(o instanceof GrVariable) && !(o instanceof GroovyResolveResult) && !(o instanceof PsiPackage); } }); } @@ -80,10 +81,6 @@ public abstract class CompletionTestBase extends JavaCodeInsightFixtureTestCase return "groovy"; } - protected boolean addKeywords() { - return true; - } - protected boolean addReferenceVariants() { return true; } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 95988ee2fb87..d84a161f0306 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -32,7 +32,7 @@ import org.jetbrains.plugins.groovy.util.TestUtils public class GroovyCompletionTest extends GroovyCompletionTestBase { @Override protected String getBasePath() { - return TestUtils.getTestDataPath() + "groovy/completion/"; + return TestUtils.testDataPath + "groovy/completion/"; } @Override @@ -41,194 +41,194 @@ public class GroovyCompletionTest extends GroovyCompletionTestBase { super.tearDown() } - public void testFinishMethodWithLParen() throws Throwable { + public void testFinishMethodWithLParen() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "getBar", "getClass", "getFoo"); myFixture.type('('); myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); } - public void testNamedParametersForApplication() throws Throwable { + public void testNamedParametersForApplication() { doVariantableTest("abx", "aby"); } - public void testNamedParametersForMethodCall() throws Throwable { + public void testNamedParametersForMethodCall() { doVariantableTest("abx", "aby"); } - public void testNamedParameters1() throws Throwable { + public void testNamedParameters1() { doVariantableTest("abx", "aby"); } - public void testNamedParameters2() throws Throwable { + public void testNamedParameters2() { doVariantableTest("abx", "aby"); } - public void testNamedParametersInMap1() throws Throwable { + public void testNamedParametersInMap1() { doVariantableTest("abx", "aby"); } - public void testNamedParametersInMap2() throws Throwable { + public void testNamedParametersInMap2() { doVariantableTest("abx", "aby"); } - public void testNamedParametersInSecondMap1() throws Throwable { + public void testNamedParametersInSecondMap1() { doVariantableTest(); } - public void testNamedParametersInSecondMap2() throws Throwable { + public void testNamedParametersInSecondMap2() { doVariantableTest(); } - public void testNamedParametersExcludeExisted() throws Throwable { + public void testNamedParametersExcludeExisted() { doVariantableTest("abx", "aby"); } - public void testNamedParametersExcludeExisted2() throws Throwable { + public void testNamedParametersExcludeExisted2() { doVariantableTest("abx", "aby", "abz"); } - public void testNamedParametersExcludeExistedMap() throws Throwable { + public void testNamedParametersExcludeExistedMap() { doVariantableTest("abx", "aby"); } - public void testNamedParametersForNotMap() throws Throwable { + public void testNamedParametersForNotMap() { doBasicTest(); } - public void testNamedParametersForConstructorCall() throws Throwable { + public void testNamedParametersForConstructorCall() { doVariantableTest("hahaha", "hohoho", "hashCode"); } - public void testUnfinishedMethodTypeParameter() throws Throwable { + public void testUnfinishedMethodTypeParameter() { doVariantableTest("MyParameter", "MySecondParameter"); } - public void testUnfinishedMethodTypeParameter2() throws Throwable { + public void testUnfinishedMethodTypeParameter2() { doVariantableTest("MyParameter", "MySecondParameter"); } - public void testInstanceofHelpsDetermineType() throws Throwable { + public void testInstanceofHelpsDetermineType() { doBasicTest(); } - public void testInstanceofHelpsDetermineTypeInBinaryAnd() throws Throwable { doBasicTest() } - public void testInstanceofHelpsDetermineTypeInBinaryOr() throws Throwable { doBasicTest() } + public void testInstanceofHelpsDetermineTypeInBinaryAnd() { doBasicTest() } + public void testInstanceofHelpsDetermineTypeInBinaryOr() { doBasicTest() } - public void testNotInstanceofDoesntHelpDetermineType() throws Throwable { + public void testNotInstanceofDoesntHelpDetermineType() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + ".groovy"); } - public void testNotInstanceofDoesntHelpDetermineType2() throws Throwable { + public void testNotInstanceofDoesntHelpDetermineType2() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + ".groovy"); } - public void testTypeParameterCompletion() throws Throwable { + public void testTypeParameterCompletion() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "put", "putAll"); } - public void testCatchClauseParameter() throws Throwable { + public void testCatchClauseParameter() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "getCause", "getClass"); } - public void testFieldSuggestedOnce1() throws Throwable { + public void testFieldSuggestedOnce1() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + ".groovy"); assertNull(myFixture.getLookupElements()); } - public void testFieldSuggestedOnce2() throws Throwable { + public void testFieldSuggestedOnce2() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + ".groovy"); assertNull(myFixture.getLookupElements()); } - public void testFieldSuggestedOnce3() throws Throwable { + public void testFieldSuggestedOnce3() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + ".groovy"); assertNull(myFixture.getLookupElements()); } - public void testFieldSuggestedOnce4() throws Throwable { + public void testFieldSuggestedOnce4() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + ".groovy"); assertNull(myFixture.getLookupElements()); } - public void testFieldSuggestedOnce5() throws Throwable { + public void testFieldSuggestedOnce5() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + ".groovy"); assertNull(myFixture.getLookupElements()); } - public void testFieldSuggestedInMethodCall() throws Throwable { + public void testFieldSuggestedInMethodCall() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy"); } - public void testMethodParameterNoSpace() throws Throwable { + public void testMethodParameterNoSpace() { myFixture.testCompletion(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy"); } - public void testGroovyDocParameter() throws Throwable { + public void testGroovyDocParameter() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "xx", "xy"); } - public void testInnerClassExtendsImplementsCompletion() throws Throwable { + public void testInnerClassExtendsImplementsCompletion() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "extends", "implements"); } - public void testInnerClassCompletion() throws Throwable { + public void testInnerClassCompletion() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "Inner1", "Inner2"); } - public void testQualifiedThisCompletion() throws Throwable { + public void testQualifiedThisCompletion() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "foo1", "foo2"); } - public void testQualifiedSuperCompletion() throws Throwable { + public void testQualifiedSuperCompletion() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "foo1", "foo2"); } - public void testThisKeywordCompletionAfterClassName1() throws Throwable { + public void testThisKeywordCompletionAfterClassName1() { doBasicTest(); } - public void testThisKeywordCompletionAfterClassName2() throws Throwable { + public void testThisKeywordCompletionAfterClassName2() { doBasicTest(); } - public void testWhileInstanceof() throws Throwable { doBasicTest() } + public void testWhileInstanceof() { doBasicTest() } - public void testCompletionInParameterListInClosableBlock() throws Throwable { doBasicTest(); } - public void testCompletionInParameterListInClosableBlock3() throws Throwable { doBasicTest(); } + public void testCompletionInParameterListInClosableBlock() { doBasicTest(); } + public void testCompletionInParameterListInClosableBlock3() { doBasicTest(); } - public void testCompletionInParameterListInClosableBlock2() throws Throwable { + public void testCompletionInParameterListInClosableBlock2() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "aDouble"); } - public void testStaticMemberFromInstanceContext() throws Throwable { + public void testStaticMemberFromInstanceContext() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "var1", "var2"); } - public void testInstanceMemberFromStaticContext() throws Throwable { + public void testInstanceMemberFromStaticContext() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "var3", "var4"); } - public void testTypeCompletionInVariableDeclaration1() throws Throwable { + public void testTypeCompletionInVariableDeclaration1() { doBasicTest(); } - public void testTypeCompletionInVariableDeclaration2() throws Throwable { + public void testTypeCompletionInVariableDeclaration2() { doBasicTest(); } - public void testTypeCompletionInParameter() throws Throwable { + public void testTypeCompletionInParameter() { doBasicTest(); } - public void testGStringConcatenationCompletion() throws Throwable { + public void testGStringConcatenationCompletion() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "substring", "substring", "subSequence"); } - public void testPropertyWithSecondUpperLetter() throws Exception { + public void testPropertyWithSecondUpperLetter() { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "geteMail", "getePost"); } - public void testInferredVariableType() throws Exception { + public void testInferredVariableType() { myFixture.configureByText "a.groovy", "def foo = 'xxx'; fo" def presentation = new LookupElementPresentation() myFixture.completeBasic()[0].renderElement(presentation) @@ -236,7 +236,7 @@ public class GroovyCompletionTest extends GroovyCompletionTestBase { assert presentation.typeText == 'String' } - public void testSubstitutedMethodType() throws Exception { + public void testSubstitutedMethodType() { myFixture.configureByText "a.groovy", "new HashMap().putx" def presentation = new LookupElementPresentation() myFixture.completeBasic()[0].renderElement(presentation) @@ -248,7 +248,7 @@ public class GroovyCompletionTest extends GroovyCompletionTestBase { public void testIntCompletionInPlusMethod() {doBasicTest();} public void testIntCompletionInGenericParameter() {doBasicTest();} - public void testWhenSiblingIsStaticallyImported_Method() throws Exception { + public void testWhenSiblingIsStaticallyImported_Method() { myFixture.addFileToProject "foo/Foo.groovy", """package foo class Foo { static def abcMethod() {} @@ -272,7 +272,7 @@ public class GroovyCompletionTest extends GroovyCompletionTestBase { """ } - public void testWhenSiblingIsStaticallyImported_Field() throws Exception { + public void testWhenSiblingIsStaticallyImported_Field() { myFixture.addFileToProject "foo/Foo.groovy", """package foo class Foo { static def abcField = 4 @@ -770,7 +770,7 @@ try {} catch (AbcdException""" myFixture.checkResult "try {} catch (AbcdException e) {}" } - public void testTopLevelClassesFromPackaged() throws Throwable { + public void testTopLevelClassesFromPackaged() { myFixture.addClass "public class Fooooo {}" final text = "package foo; class Bar { Fooo }" def file = myFixture.addFileToProject("foo/Bar.groovy", text) @@ -845,17 +845,17 @@ return foo()""" checkCompletion("new Abcd", '<', "new AbcdClass<>()") } - public void testMapKeysUsedInFile() throws Exception { + public void testMapKeysUsedInFile() { CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE doVariantableTest 'foo1', 'foo3', 'foo4', 'Foo5', 'Foo7' } - public void testNoClassesAsMapKeys() throws Exception { + public void testNoClassesAsMapKeys() { CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE doVariantableTest() } - public void testNamedArgsUsedInFile() throws Exception { + public void testNamedArgsUsedInFile() { myFixture.configureByFile(getTestName(false) + ".groovy"); doVariantableTest 'false', 'foo2', 'float', 'foo1', 'foo3', 'foo4', 'foo5' } @@ -877,7 +877,7 @@ class A { }''' } - public void testSuperClassProperty() throws Exception { + public void testSuperClassProperty() { checkSingleItemCompletion """ class A { def foooooooooooo } @@ -967,7 +967,7 @@ println "abcd" ''') } - public void testNoModifiersAfterDef() throws Exception { + public void testNoModifiersAfterDef() { checkSingleItemCompletion 'def priv', 'def priv' } @@ -1079,19 +1079,19 @@ class X { checkCompletion 'byte v1 = (byte) 0', '\t', 'byte v1 = (byte) 0' } - public void testInitializerMatters() throws Exception { + public void testInitializerMatters() { myFixture.configureByText("a.groovy", "class Foo {{ String fx = getFoo(); }; String getFoo() {}; }"); myFixture.completeBasic() assertOrderedEquals(myFixture.lookupElementStrings, ["foo"]) } - public void testFieldInitializerMatters() throws Exception { + public void testFieldInitializerMatters() { myFixture.configureByText("a.groovy", "class Foo { String fx = getFoo(); String getFoo() {}; }"); myFixture.completeBasic() assertOrderedEquals(myFixture.lookupElementStrings, ["foo"]) } - public void testAccessStaticViaInstanceSecond() throws Exception { + public void testAccessStaticViaInstanceSecond() { myFixture.configureByText("a.groovy", """ public class KeyVO { { this.fox } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/InjectedGroovyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/InjectedGroovyTest.groovy index ec9a72e32c68..cd04b5caa43f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/InjectedGroovyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/InjectedGroovyTest.groovy @@ -23,7 +23,7 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.intellij.plugins.intelliLang.inject.TemporaryPlacesRegistry import org.jetbrains.plugins.groovy.GroovyFileType -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil /** * @author peter @@ -54,7 +54,7 @@ s.codePointAt(0) def offset = psiFile.getText().indexOf('"') + 1 assertNotNull(psiFile.findElementAt(offset)); - assert InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(psiFile, offset) + assert InjectedLanguageUtil.findInjectedPsiNoCommit(psiFile, offset) } public void testRegexInjections() { @@ -62,8 +62,8 @@ s.codePointAt(0) final PsiFile psiFile = myFixture.configureByText("script.groovy", 'new groovy.lang.GroovyShell().evaluate(/ blah-blah-blah \\ language won\'t be injected here /)'); assertNotNull(psiFile); - assert InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(psiFile, psiFile.getText().indexOf('blah') + 1) - assert InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(psiFile, psiFile.getText().indexOf('injected') + 1) + assert InjectedLanguageUtil.findInjectedPsiNoCommit(psiFile, psiFile.getText().indexOf('blah') + 1) + assert InjectedLanguageUtil.findInjectedPsiNoCommit(psiFile, psiFile.getText().indexOf('injected') + 1) } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy new file mode 100644 index 000000000000..6e67ddc63c93 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy @@ -0,0 +1,101 @@ +/* + * Copyright 2000-2007 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 org.jetbrains.plugins.groovy.completion + +import org.jetbrains.plugins.groovy.util.TestUtils + +/** + * @author ilyas + */ +public class KeywordCompletionTest extends CompletionTestBase { + + void testBr1() { doTest() } + void testCase_return() { doTest() } + void testClass1() { doTest() } + void testClass2() { doTest() } + void testClass3() { doTest() } + void testClass4() { doTest() } + void testExpr1() { doTest() } + void testExpr2() { doTest() } + void testFile11() { doTest() } + void testFile12() { doTest() } + void testFin() { doTest() } + void testFin2() { doTest() } + void testGRVY1064() { doTest() } + void testGrvy1404() { doTest() } + void testImp1() { doTest() } + void testImp2() { doTest() } + void testImp3() { doTest() } + void _testImp4() { doTest() } + void testIns1() { doTest() } + void testIns2() { doTest() } + void testIns3() { doTest() } + void testInt1() { doTest() } + void testLocal1() { doTest() } + void testMod1() { doTest() } + void testMod10() { doTest() } + void testMod11() { doTest() } + void testMod2() { doTest() } + void testMod3() { doTest() } + void testMod4() { doTest() } + void testMod5() { doTest() } + void testMod6() { doTest() } + void testMod7() { doTest() } + void testMod8() { doTest() } + void testMod9() { doTest() } + void testPack1() { doTest() } + void testSt1() { doTest() } + void testSwit1() { doTest() } + void testSwit13() { doTest() } + void testSwit14() { doTest() } + void testSwit2() { doTest() } + void testSwit3() { doTest() } + void testSwit4() { doTest() } + void testSwit5() { doTest() } + void testTag1() { doTest() } + void testTag2() { doTest() } + void testTag3() { doTest() } + void testTag4() { doTest() } + void testTh1() { doTest() } + void testTh2() { doTest() } + void testVar1() { doTest() } + void testVar10() { doTest() } + void testVar13() { doTest() } + void testVar2() { doTest() } + void testVar3() { doTest() } + void testVar4() { doTest() } + void testVar5() { doTest() } + void testVar6() { doTest() } + void testVar7() { doTest() } + void testVar8() { doTest() } + void testWhile55() { doTest() } + void testDefInsideCase() { doTest() } + void testThrows1() { doTest() } + void testThrows2() { doTest() } + void testThrows3() { doTest() } + void testPrimitiveTypes() { doTest() } + + @Override + protected String getBasePath() { + "${TestUtils.testDataPath}groovy/oldCompletion/keyword" + } + + @Override + protected boolean addReferenceVariants() { + false + } + +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.java deleted file mode 100644 index bcb21b00bf34..000000000000 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2000-2007 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 org.jetbrains.plugins.groovy.completion; - -import org.jetbrains.plugins.groovy.util.TestUtils; - -/** - * @author ilyas - */ -public class KeywordCompletionTest extends CompletionTestBase { - - public void testBr1() throws Throwable { doTest(); } - public void testCase_return() throws Throwable { doTest(); } - public void testClass1() throws Throwable { doTest(); } - public void testClass2() throws Throwable { doTest(); } - public void testClass3() throws Throwable { doTest(); } - public void testClass4() throws Throwable { doTest(); } - public void testExpr1() throws Throwable { doTest(); } - public void testExpr2() throws Throwable { doTest(); } - public void testFile11() throws Throwable { doTest(); } - public void testFile12() throws Throwable { doTest(); } - public void testFin() throws Throwable { doTest(); } - public void testFin2() throws Throwable { doTest(); } - public void testGRVY1064() throws Throwable { doTest(); } - public void testGrvy1404() throws Throwable { doTest(); } - public void testImp1() throws Throwable { doTest(); } - public void testImp2() throws Throwable { doTest(); } - public void testImp3() throws Throwable { doTest(); } - public void testImp4() throws Throwable { doTest(); } - public void testIns1() throws Throwable { doTest(); } - public void testIns2() throws Throwable { doTest(); } - public void testIns3() throws Throwable { doTest(); } - public void testInt1() throws Throwable { doTest(); } - public void testLocal1() throws Throwable { doTest(); } - public void testMod1() throws Throwable { doTest(); } - public void testMod10() throws Throwable { doTest(); } - public void testMod11() throws Throwable { doTest(); } - public void testMod2() throws Throwable { doTest(); } - public void testMod3() throws Throwable { doTest(); } - public void testMod4() throws Throwable { doTest(); } - public void testMod5() throws Throwable { doTest(); } - public void testMod6() throws Throwable { doTest(); } - public void testMod7() throws Throwable { doTest(); } - public void testMod8() throws Throwable { doTest(); } - public void testMod9() throws Throwable { doTest(); } - public void testPack1() throws Throwable { doTest(); } - public void testSt1() throws Throwable { doTest(); } - public void testSwit1() throws Throwable { doTest(); } - public void testSwit13() throws Throwable { doTest(); } - public void testSwit14() throws Throwable { doTest(); } - public void testSwit2() throws Throwable { doTest(); } - public void testSwit3() throws Throwable { doTest(); } - public void testSwit4() throws Throwable { doTest(); } - public void testSwit5() throws Throwable { doTest(); } - public void testTag1() throws Throwable { doTest(); } - public void testTag2() throws Throwable { doTest(); } - public void testTag3() throws Throwable { doTest(); } - public void testTag4() throws Throwable { doTest(); } - public void testTh1() throws Throwable { doTest(); } - public void testTh2() throws Throwable { doTest(); } - public void testVar1() throws Throwable { doTest(); } - public void testVar10() throws Throwable { doTest(); } - public void testVar13() throws Throwable { doTest(); } - public void testVar2() throws Throwable { doTest(); } - public void testVar3() throws Throwable { doTest(); } - public void testVar4() throws Throwable { doTest(); } - public void testVar5() throws Throwable { doTest(); } - public void testVar6() throws Throwable { doTest(); } - public void testVar7() throws Throwable { doTest(); } - public void testVar8() throws Throwable { doTest(); } - public void testWhile55() throws Throwable { doTest(); } - public void testDefInsideCase() throws Throwable { doTest(); } - - - @Override - protected String getBasePath() { - return TestUtils.getTestDataPath() + "groovy/oldCompletion/keyword"; - } - - @Override - protected boolean addReferenceVariants() { - return false; - } - -} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/ReferenceCompletionTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/ReferenceCompletionTest.java index 388bc568d68d..30eaebab80ef 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/ReferenceCompletionTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/ReferenceCompletionTest.java @@ -54,11 +54,6 @@ public class ReferenceCompletionTest extends CompletionTestBase { return TestUtils.getTestDataPath() + "groovy/oldCompletion/reference"; } - @Override - protected boolean addKeywords() { - return false; - } - @Override protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) { moduleBuilder.addJdk(TestUtils.getMockJdkHome()); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ConvertStringToMultilineTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ConvertStringToMultilineTest.groovy new file mode 100644 index 000000000000..144dc9884b40 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ConvertStringToMultilineTest.groovy @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.plugins.groovy.intentions + +import com.intellij.openapi.application.WriteAction +import org.jetbrains.annotations.Nullable +import org.jetbrains.plugins.groovy.LightGroovyTestCase +import org.jetbrains.plugins.groovy.intentions.conversions.ConvertStringToMultilineIntention + +/** + * @author Max Medvedev + */ +public class ConvertStringToMultilineTest extends LightGroovyTestCase { + @Override + protected String getBasePath() {''} + + void testPlainString() { + doTest("print 'abc'", "print '''abc'''") + } + + void testGString() { + doTest('print "abc"', 'print """abc"""') + } + + void testPlainString2() { + doTest("print 'a\\nbc'", "print '''a\nbc'''") + } + + void testGString2() { + doTest('print "a\\nbc"', 'print """a\nbc"""') + } + + void testGString3() { + doTest('print "a\\nb${a}c"', 'print """a\nb${a}c"""') + } + + void testAlreadyMultiline() { + doTest('print """abc"""', null) + } + + private doTest(String before, @Nullable String after) { + myFixture.with { + configureByText('_.groovy', before) + def intentions = filterAvailableIntentions(ConvertStringToMultilineIntention.hint) + if (!after) { + assertEmpty(intentions) + return + } + + assertOneElement(intentions) + def accessToken = WriteAction.start() + try { + intentions[0].invoke(project, editor, file) + } + finally { + accessToken.finish() + } + checkResult(after) + } + } +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy index 516ae9c842a7..8156066ce4b5 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy @@ -51,7 +51,7 @@ class CreateFieldFromParameterTest extends LightCodeInsightFixtureTestCase { void testTypeParameter() {doTest()} private void doTest() { - myFixture.configureByFile("before${getTestName(true)}.groovy") + myFixture.configureByFile("before${getTestName(false)}.groovy") def intentions = myFixture.availableIntentions for (intention in intentions) { if (intention instanceof IntentionActionWrapper) intention = intention.delegate @@ -61,6 +61,6 @@ class CreateFieldFromParameterTest extends LightCodeInsightFixtureTestCase { break } } - myFixture.checkResultByFile("after${getTestName(true)}.groovy") + myFixture.checkResultByFile("after${getTestName(false)}.groovy") } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy index a25f727d2e73..26940d26dc31 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy @@ -19,20 +19,10 @@ package org.jetbrains.plugins.groovy.lang; import com.intellij.codeInspection.InspectionProfileEntry import com.intellij.codeInspection.LocalInspectionTool import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection -import com.intellij.openapi.module.Module -import com.intellij.openapi.roots.ContentEntry -import com.intellij.openapi.roots.ModifiableRootModel -import com.intellij.openapi.roots.OrderRootType -import com.intellij.openapi.roots.libraries.Library -import com.intellij.openapi.vfs.JarFileSystem -import com.intellij.openapi.vfs.VirtualFile import com.intellij.testFramework.IdeaTestUtil -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.siyeh.ig.junit.JUnitAbstractTestClassNamingConventionInspection import com.siyeh.ig.junit.JUnitTestClassNamingConventionInspection -import org.jetbrains.annotations.NotNull +import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyResultOfAssignmentUsedInspection @@ -50,34 +40,15 @@ import org.jetbrains.plugins.groovy.util.TestUtils import org.jetbrains.plugins.groovy.codeInspection.bugs.* import org.jetbrains.plugins.groovy.codeInspection.confusing.* -import static org.jetbrains.plugins.groovy.util.TestUtils.getMockGroovy1_8LibraryName - /** * @author peter */ -public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase { - public static final DefaultLightProjectDescriptor GROOVY_18_PROJECT_DESCRIPTOR = new DefaultLightProjectDescriptor() { - @Override - public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) { - final Library.ModifiableModel modifiableModel = model.moduleLibraryTable.createLibrary("GROOVY").modifiableModel; - final VirtualFile groovyJar = JarFileSystem.instance.refreshAndFindFileByPath(mockGroovy1_8LibraryName + '!/'); - assertTrue(groovyJar != null); - modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES); - modifiableModel.commit(); - } - }; - +public class GroovyHighlightingTest extends LightGroovyTestCase { @Override protected String getBasePath() { return TestUtils.testDataPath + 'highlighting/'; } - @NotNull - @Override - protected LightProjectDescriptor getProjectDescriptor() { - return GROOVY_18_PROJECT_DESCRIPTOR; - } - public void testDuplicateClosurePrivateVariable() throws Throwable { doTest(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressPerformanceTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressPerformanceTest.groovy index 6063fc8290c5..57ae870a8ec1 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressPerformanceTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressPerformanceTest.groovy @@ -3,24 +3,20 @@ package org.jetbrains.plugins.groovy.lang import com.intellij.psi.PsiClass import com.intellij.psi.PsiDocumentManager import com.intellij.testFramework.IdeaTestUtil -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase -import org.jetbrains.annotations.NotNull +import com.intellij.util.ThrowableRunnable import org.jetbrains.plugins.groovy.LightGroovyTestCase +import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager -import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection -import com.intellij.util.ThrowableRunnable /** * @author peter */ -class GroovyStressPerformanceTest extends LightCodeInsightFixtureTestCase { - @NotNull - @Override protected LightProjectDescriptor getProjectDescriptor() { - LightGroovyTestCase.GROOVY_DESCRIPTOR - } +class GroovyStressPerformanceTest extends LightGroovyTestCase { + + @Override + protected String getBasePath() {''} ThrowableRunnable configureAndHighlight(String text) { return { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy index 538fac39a666..ca4da0763c8a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy @@ -1,28 +1,20 @@ package org.jetbrains.plugins.groovy.lang; -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase -import org.jetbrains.annotations.NotNull +import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection import org.jetbrains.plugins.groovy.util.TestUtils /** * @author peter */ -public class MissingReturnTest extends LightCodeInsightFixtureTestCase { +public class MissingReturnTest extends LightGroovyTestCase { @Override protected String getBasePath() { return "${TestUtils.testDataPath}highlighting/missingReturn"; } - @NotNull - @Override - protected LightProjectDescriptor getProjectDescriptor() { - return GroovyHighlightingTest.GROOVY_18_PROJECT_DESCRIPTOR; - } - public void testMissingReturnWithLastLoop() throws Throwable { doTest(); } public void testMissingReturnWithUnknownCall() throws Throwable { doTest(); } public void testMissingReturnWithIf() throws Throwable { doTest(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java index 3298d637fc22..046a585f9f7e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java @@ -60,7 +60,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase { public void testAnonymous() {doTest();} public void testSomeCatches() {doTest();} public void testOrInReturn() {doTest();} - public void testInString() {doTest();} + public void testVarInString() {doTest();} public void doTest() { final List input = TestUtils.readInput(getTestDataPath() + getTestName(true) + ".test"); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy index cc9229809b73..f19b82d345a3 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy @@ -1070,4 +1070,17 @@ extensionClasses=pack.StringExt assertNotNull(ref.resolve()) } + + void testInitializerOfScriptField() { + addGroovyTransformField() + def ref = configureByText('''\ +import groovy.transform.Field + +def xx(){5} + +@Field +def aa = 5 + xx() +''') + assertInstanceOf(ref.resolve(), GrMethod) + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy index 24be0c7871be..d5b7ee1086e4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy @@ -684,7 +684,7 @@ setFoo(2) } public void testFieldTransform() { - myFixture.addClass('package groovy.transform; public @interface Field {}') + addGroovyTransformField() def ref = configureByText("""@groovy.transform.Field def aaa = 2 def foo() { println aaa } """) @@ -800,4 +800,68 @@ new A().prop''') assertEquals(method.parameterList.parameters[0].type.canonicalText, CommonClassNames.JAVA_LANG_STRING) } + + void testLocalVarNotAvailableInClass() { + def ref = configureByText('''\ +def aa = 5 + +class Inner { + def foo() { + print aa + } +}''') + assertNull(ref.resolve()) + } + + void testLocalVarNotAvailableInMethod() { + def ref = configureByText('''\ +def aa = 5 + +def foo() { + print aa +}''') + assertNull(ref.resolve()) + } + + void testScriptFieldNotAvailableInClass() { + addGroovyTransformField() + def ref = configureByText('''\ +import groovy.transform.Field + +@Field +def aa = 5 + +class X { + def foo() { + print aa + } +}''') + assertNull(ref.resolve()) + } + + void testInitializerOfScriptField() { + addGroovyTransformField() + def ref = configureByText('''\ +import groovy.transform.Field + +def xx = 5 +@Field +def aa = 5 + xx +''') + assertNull(ref.resolve()) + } + + void testInitializerOfScriptField2() { + addGroovyTransformField() + def ref = configureByText('''\ +import groovy.transform.Field + +@Field +def xx = 5 + +@Field +def aa = 5 + xx +''') + assertInstanceOf(ref.resolve(), GrVariable) + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy new file mode 100644 index 000000000000..8e4b2c3a1e0c --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy @@ -0,0 +1,192 @@ +/* + * Copyright 2000-2011 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 org.jetbrains.plugins.groovy.refactoring.introduce.field; + + +import com.intellij.openapi.application.WriteAction +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiType +import com.intellij.psi.impl.source.PostprocessReformattingAspect +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable +import org.jetbrains.plugins.groovy.LightGroovyTestCase +import org.jetbrains.plugins.groovy.util.TestUtils + +import static org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldSettings.Init.* + +/** + * @author Maxim.Medvedev + */ +public class GrIntroduceFieldTest extends LightGroovyTestCase { + @Override + protected String getBasePath() { + "${TestUtils.testDataPath}refactoring/introduceField/"; + } + + public void testSimple() { + doTest(false, false, false, CUR_METHOD, false, null); + } + + public void testDeclareFinal() { + doTest(false, false, true, FIELD_DECLARATION, false, null); + } + + public void testCreateConstructor() { + doTest(false, false, true, CONSTRUCTOR, true, null); + } + + public void testManyConstructors() { + doTest(false, false, true, CONSTRUCTOR, true, null); + } + + public void testDontReplaceStaticOccurrences() { + doTest(false, false, true, FIELD_DECLARATION, true, null); + } + + public void testQualifyUsages() { + doTest(false, false, true, FIELD_DECLARATION, true, null); + } + + public void testReplaceLocalVar() { + doTest(false, true, false, CUR_METHOD, true, null); + } + + public void testIntroduceLocalVarByDeclaration() { + doTest(false, true, false, FIELD_DECLARATION, true, null); + } + + public void testReplaceExpressionWithAssignment() { + doTest(false, false, false, CUR_METHOD, false, null); + } + + public void testAnonymousClass() { + doTest(false, false, false, CUR_METHOD, false, null); + } + + public void testAnonymous2() { + doTest(false, false, false, CONSTRUCTOR, false, null); + } + + public void testAnonymous3() { + doTest(false, false, false, CONSTRUCTOR, false, null); + } + + public void testInitializeInCurrentMethod() { + doTest(false, true, true, CUR_METHOD, false, null); + } + + public void testScriptBody() { + addGroovyTransformField() + doTest('''\ +print 'abc' +''', '''\ +import groovy.transform.Field + +@Field f = 'abc' +print f +''', false, false, false, FIELD_DECLARATION) + } + + public void testScriptMethod() { + addGroovyTransformField() + doTest('''\ +def foo() { + print 'abc' +} +''', '''\ +import groovy.transform.Field + +@Field final f = 'abc' + +def foo() { + print f +} +''', false, false, true, FIELD_DECLARATION) + } + + public void testStaticScriptMethod() { + addGroovyTransformField() + doTest('''\ +static def foo() { + print 'abc' +} +''', '''\ +import groovy.transform.Field + +@Field static f = 'abc' + +static def foo() { + print f +} +''', true, false, false, FIELD_DECLARATION) + } + + public void testScriptMethod2() { + addGroovyTransformField() + doTest('''\ +def foo() { + print 'abc' +} +''', '''\ +import groovy.transform.Field + +@Field f + +def foo() { + f = 'abc' + print f +} +''', false, false, false, CUR_METHOD) + } + + private void doTest(final boolean isStatic, + final boolean removeLocal, + final boolean declareFinal, + @NotNull final GrIntroduceFieldSettings.Init initIn, + final boolean replaceAll = false, + @Nullable final String selectedType = null) { + myFixture.configureByFile("${getTestName(false)}.groovy") + performRefactoring(selectedType, isStatic, removeLocal, declareFinal, initIn, replaceAll) + myFixture.checkResultByFile("${getTestName(false)}_after.groovy"); + } + + private void doTest(@NotNull final String textBefore, + @NotNull String textAfter, + final boolean isStatic, + final boolean removeLocal, + final boolean declareFinal, + @NotNull final GrIntroduceFieldSettings.Init initIn, + final boolean replaceAll = false, + @Nullable final String selectedType = null) { + myFixture.configureByText("_.groovy", textBefore) + performRefactoring(selectedType, isStatic, removeLocal, declareFinal, initIn, replaceAll) + myFixture.checkResult(textAfter); + } + + + private void performRefactoring(String selectedType, boolean isStatic, boolean removeLocal, boolean declareFinal, GrIntroduceFieldSettings.Init initIn, boolean replaceAll) { + final PsiType type = selectedType == null ? null : JavaPsiFacade.getElementFactory(project).createTypeFromText(selectedType, myFixture.file) + def accessToken = WriteAction.start() + try { + final IntroduceFieldTestHandler handler = new IntroduceFieldTestHandler(isStatic, removeLocal, declareFinal, initIn, replaceAll, type) + handler.invoke(project, myFixture.editor, myFixture.file, null); + PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); + } + finally { + accessToken.finish() + } + } +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.java deleted file mode 100644 index 959f4a8742ad..000000000000 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2000-2011 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 org.jetbrains.plugins.groovy.refactoring.introduce.field; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiType; -import com.intellij.psi.impl.source.PostprocessReformattingAspect; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.util.TestUtils; - -import static org.jetbrains.plugins.groovy.refactoring.introduce.field.GrIntroduceFieldSettings.Init.*; - -/** - * @author Maxim.Medvedev - */ -public class GrIntroduceFieldTest extends LightCodeInsightFixtureTestCase { - @Override - protected String getBasePath() { - return TestUtils.getTestDataPath() + "refactoring/introduceField/"; - } - - public void testSimple() { - doTest(false, false, false, CUR_METHOD, false, null); - } - - public void testDeclareFinal() { - doTest(false, false, true, FIELD_DECLARATION, false, null); - } - - public void testCreateConstructor() { - doTest(false, false, true, CONSTRUCTOR, true, null); - } - - public void testManyConstructors() { - doTest(false, false, true, CONSTRUCTOR, true, null); - } - - public void testDontReplaceStaticOccurrences() { - doTest(false, false, true, FIELD_DECLARATION, true, null); - } - - public void testQualifyUsages() { - doTest(false, false, true, FIELD_DECLARATION, true, null); - } - - public void testReplaceLocalVar() { - doTest(false, true, false, CUR_METHOD, true, null); - } - - public void testIntroduceLocalVarByDeclaration() { - doTest(false, true, false, FIELD_DECLARATION, true, null); - } - - public void testReplaceExpressionWithAssignment() { - doTest(false, false, false, CUR_METHOD, false, null); - } - - public void testAnonymousClass() { - doTest(false, false, false, CUR_METHOD, false, null); - } - - public void testAnonymous2() { - doTest(false, false, false, CONSTRUCTOR, false, null); - } - - public void testAnonymous3() { - doTest(false, false, false, CONSTRUCTOR, false, null); - } - - public void testInitializeInCurrentMethod() { - doTest(false, true, true, CUR_METHOD, false, null); - } - - private void doTest(final boolean isStatic, - final boolean removeLocal, - final boolean declareFinal, - final GrIntroduceFieldSettings.Init initIn, - final boolean replaceAll, - @Nullable final String selectedType) { - myFixture.configureByFile(getTestName(false) + ".groovy"); - - final PsiType type = - selectedType == null ? null : JavaPsiFacade.getElementFactory(getProject()).createTypeFromText(selectedType, myFixture.getFile()); - - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - final IntroduceFieldTestHandler handler = - new IntroduceFieldTestHandler(isStatic, removeLocal, declareFinal, initIn, replaceAll, type); - handler.invoke(getProject(), myFixture.getEditor(), myFixture.getFile(), null); - PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting(); - } - }); - - myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); - } -} diff --git a/plugins/groovy/testdata/groovy/controlFlow/InString.test b/plugins/groovy/testdata/groovy/controlFlow/varInString.test similarity index 100% rename from plugins/groovy/testdata/groovy/controlFlow/InString.test rename to plugins/groovy/testdata/groovy/controlFlow/varInString.test diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/imp4.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/imp4.test deleted file mode 100644 index 35f7f2ff4ddb..000000000000 --- a/plugins/groovy/testdata/groovy/oldCompletion/keyword/imp4.test +++ /dev/null @@ -1,6 +0,0 @@ -import static a.b ------ -META-INF -java -javax -org \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/primitiveTypes.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/primitiveTypes.test new file mode 100644 index 000000000000..7b24b36202ad --- /dev/null +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/primitiveTypes.test @@ -0,0 +1,31 @@ +class X { + def foo() + + +} +----- +abstract +boolean +byte +char +class +def +double +enum +final +float +int +interface +long +native +private +protected +public +short +static +strictfp +synchronized +throws +transient +void +volatile \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/th2.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/th2.test index f6c5113fc213..1933b4acca81 100644 --- a/plugins/groovy/testdata/groovy/oldCompletion/keyword/th2.test +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/th2.test @@ -2,4 +2,7 @@ class A{ static A() } ----- +class +enum +interface throws \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws1.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws1.test new file mode 100644 index 000000000000..3edcd11e7e4c --- /dev/null +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws1.test @@ -0,0 +1,5 @@ +class X { + def foo() th +} +----- +throws \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws2.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws2.test new file mode 100644 index 000000000000..93cc2df97b50 --- /dev/null +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws2.test @@ -0,0 +1,5 @@ +class X { + def foo() th {} +} +----- +throws \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws3.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws3.test new file mode 100644 index 000000000000..a843e28284dd --- /dev/null +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/throws3.test @@ -0,0 +1,4 @@ +class X { + def foo(); th +} +----- diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/var13.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/var13.test index 58151b4ec46d..72f1e3bece98 100644 --- a/plugins/groovy/testdata/groovy/oldCompletion/keyword/var13.test +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/var13.test @@ -11,7 +11,6 @@ class A { } ----- -META-INF abstract boolean byte @@ -24,11 +23,8 @@ final float int interface -java -javax long native -org private protected public diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/var3.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/var3.test index d77d173b6cc5..c26b3e8a7eb4 100644 --- a/plugins/groovy/testdata/groovy/oldCompletion/keyword/var3.test +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/var3.test @@ -10,8 +10,4 @@ class A { } } ----- -META-INF -java -javax -org static \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/var6.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/var6.test index 53edfa257c61..923580443c31 100644 --- a/plugins/groovy/testdata/groovy/oldCompletion/keyword/var6.test +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/var6.test @@ -10,7 +10,6 @@ class A { } } ----- -META-INF abstract boolean byte @@ -23,11 +22,8 @@ final float int interface -java -javax long native -org private protected public diff --git a/plugins/groovy/testdata/intentions/staticImport/SingleImport3_after.groovy b/plugins/groovy/testdata/intentions/staticImport/SingleImport3_after.groovy index 618a7106ce31..cb0e6425f167 100644 --- a/plugins/groovy/testdata/intentions/staticImport/SingleImport3_after.groovy +++ b/plugins/groovy/testdata/intentions/staticImport/SingleImport3_after.groovy @@ -1,5 +1,3 @@ -import static Util.doSomething - class Util { static doSomething(){} } diff --git a/plugins/groovy/testdata/refactoring/introduceField/Anonymous2_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/Anonymous2_after.groovy index f7ccc4a47f5b..cebc36fe407d 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/Anonymous2_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/Anonymous2_after.groovy @@ -7,6 +7,7 @@ def a = new A() { f = 123 } int i + def f @Override diff --git a/plugins/groovy/testdata/refactoring/introduceField/Anonymous3_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/Anonymous3_after.groovy index bc413dbeba86..84dd753e25d8 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/Anonymous3_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/Anonymous3_after.groovy @@ -4,11 +4,12 @@ interface A { def a = new A() { int i - def f { f = 123 } + def f + @Override void m1() { println f diff --git a/plugins/groovy/testdata/refactoring/introduceField/CreateConstructor_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/CreateConstructor_after.groovy index ddb1a3213ee7..185bb4ccc060 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/CreateConstructor_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/CreateConstructor_after.groovy @@ -1,5 +1,5 @@ class Bar { - final def f + final f Bar() { f = "foo" diff --git a/plugins/groovy/testdata/refactoring/introduceField/DeclareFinal_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/DeclareFinal_after.groovy index c043a69a68f7..592c0d8d49f6 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/DeclareFinal_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/DeclareFinal_after.groovy @@ -1,6 +1,7 @@ class Foo { def bar = 5 - final def f = bar + 5 + + final f = bar + 5 def foo() { print f diff --git a/plugins/groovy/testdata/refactoring/introduceField/DontReplaceStaticOccurrences_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/DontReplaceStaticOccurrences_after.groovy index 59ab81894e63..4363b4c6a8e7 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/DontReplaceStaticOccurrences_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/DontReplaceStaticOccurrences_after.groovy @@ -1,6 +1,7 @@ class Bar { static int x = 5 - final def f = x + 2 + + final f = x + 2 def foo() { print f diff --git a/plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy index e126a9b38c03..d7a1b54a8d3b 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/InitializeInCurrentMethod_after.groovy @@ -1,5 +1,5 @@ class X { - final def f + final f def foo() { if (true) { diff --git a/plugins/groovy/testdata/refactoring/introduceField/ManyConstructors_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/ManyConstructors_after.groovy index 85b9a7d34e21..43ff2a6ac261 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/ManyConstructors_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/ManyConstructors_after.groovy @@ -1,5 +1,5 @@ class Bar { - final def f + final f def Bar() { super() diff --git a/plugins/groovy/testdata/refactoring/introduceField/QualifyUsages_after.groovy b/plugins/groovy/testdata/refactoring/introduceField/QualifyUsages_after.groovy index 1dd2b2e207d5..c50f1f8e3ce0 100644 --- a/plugins/groovy/testdata/refactoring/introduceField/QualifyUsages_after.groovy +++ b/plugins/groovy/testdata/refactoring/introduceField/QualifyUsages_after.groovy @@ -1,5 +1,5 @@ class Bar { - final def f = "bar" + final f = "bar" def foo() { def f = 5 diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java index dad8077bb62e..f674084163a0 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/SuppressByCommentOutAction.java @@ -24,7 +24,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; @@ -45,7 +45,7 @@ class SuppressByCommentOutAction extends SuppressIntentionAction { if (!CodeInsightUtilBase.preparePsiElementForWrite(element)) return; element = findJavaCodeUpThere(element); PsiFile file = element.getContainingFile(); - editor = InjectedLanguageFacadeImpl.openEditorFor(file, project); + editor = InjectedLanguageUtil.openEditorFor(file, project); int endOffset = element.getTextRange().getEndOffset(); int line = editor.getDocument().getLineNumber(endOffset); int lineEndOffset = editor.getDocument().getLineEndOffset(line); diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java b/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java index 407a4cf0ccdc..2bf1a9205d96 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java @@ -27,7 +27,7 @@ import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.refactoring.actions.RenameElementAction; import com.intellij.refactoring.rename.NameSuggestionProvider; import com.intellij.refactoring.rename.RenameHandlerRegistry; @@ -86,7 +86,7 @@ public class RenameTo extends ShowSuggestions implements SpellCheckerQuickFix { HashMap map = new HashMap(); PsiElement psiElement = descriptor.getPsiElement(); PsiFile containingFile = psiElement.getContainingFile(); - Editor editor = InjectedLanguageFacadeImpl.openEditorFor(containingFile, project); + Editor editor = InjectedLanguageUtil.openEditorFor(containingFile, project); if (editor == null) { return; } diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/TokenizerBase.java b/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/TokenizerBase.java index d9b83abbd6c8..5210dbe5e639 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/TokenizerBase.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/TokenizerBase.java @@ -17,7 +17,7 @@ package com.intellij.spellchecker.tokenizer; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.spellchecker.inspections.Splitter; import org.jetbrains.annotations.NotNull; @@ -37,7 +37,7 @@ public class TokenizerBase extends Tokenizer { @Override public void tokenize(@NotNull T element, TokenConsumer consumer) { - if (element instanceof PsiLanguageInjectionHost && InjectedLanguageFacadeImpl.hasInjections((PsiLanguageInjectionHost)element)) { + if (element instanceof PsiLanguageInjectionHost && InjectedLanguageUtil.hasInjections((PsiLanguageInjectionHost)element)) { return; } consumer.consumeToken(element, mySplitter); diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/XmlTextTokenizer.java b/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/XmlTextTokenizer.java index 3864f8e04691..485e867cb929 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/XmlTextTokenizer.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/XmlTextTokenizer.java @@ -18,7 +18,7 @@ package com.intellij.spellchecker.tokenizer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.xml.XmlText; import com.intellij.psi.xml.XmlToken; import com.intellij.psi.xml.XmlTokenType; @@ -30,7 +30,7 @@ import java.util.List; public class XmlTextTokenizer extends Tokenizer { @Override public void tokenize(@NotNull XmlText element, TokenConsumer consumer) { - List> list = InjectedLanguageFacadeImpl.getInstance().getInjectedPsiFiles(element); + List> list = InjectedLanguageUtil.getInstance().getInjectedPsiFiles(element); if (list != null && list.size() > 0) return; final PsiElement[] children = element.getChildren(); for (PsiElement child : children) { diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java index 07b4583f667f..c66f50cd188c 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java @@ -20,6 +20,7 @@ import com.intellij.designer.model.RadComponent; import com.intellij.designer.propertyTable.InplaceContext; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPopupMenu; +import com.intellij.openapi.util.SystemInfo; import org.jetbrains.annotations.Nullable; import java.awt.event.InputEvent; @@ -148,7 +149,7 @@ public class SelectionTool extends InputTool { myTracker.mouseUp(event, area); } super.mouseUp(event, area); - if (event.isPopupTrigger()) { + if (event.isPopupTrigger() || (SystemInfo.isMac && event.getButton() == MouseEvent.BUTTON3)) { ActionManager actionManager = ActionManager.getInstance(); ActionPopupMenu popupMenu = actionManager.createActionPopupMenu(area.getPopupPlace(), area.getPopupActions()); popupMenu.getComponent().show(area.getNativeComponent(), event.getX(), event.getY()); diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/XPathElementImpl.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/XPathElementImpl.java index b4ffb6a8298d..728bbee7c3d3 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/XPathElementImpl.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/XPathElementImpl.java @@ -21,7 +21,7 @@ import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.impl.PsiTreeDebugBuilder; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.IncorrectOperationException; import org.intellij.lang.xpath.XPath2ElementTypes; import org.intellij.lang.xpath.XPathElementTypes; @@ -141,7 +141,7 @@ public class XPathElementImpl extends ASTWrapperPsiElement implements XPathEleme } public final String getUnescapedText() { - if (InjectedLanguageFacadeImpl.isInInjectedLanguagePrefixSuffix(this)) { + if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(this)) { // do not attempt to decode text if PsiElement is part of prefix/suffix return getText(); } diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java index a73a30a3e741..76887f89f3eb 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java @@ -22,7 +22,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.impl.PsiFileEx; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.*; import com.intellij.psi.xml.*; import com.intellij.ui.LayeredIcon; @@ -88,7 +88,7 @@ public class XsltSupport { final XmlAttributeValue value = attribute.getValueElement(); if (value != null) { final List files = new SmartList(); - InjectedLanguageFacadeImpl.enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() { + InjectedLanguageUtil.enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { if (injectedPsi instanceof XPathFile) { files.add(injectedPsi); diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/XsltCodeInsightUtil.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/XsltCodeInsightUtil.java index 65baf53f6eae..99dd59d7acd9 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/XsltCodeInsightUtil.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/XsltCodeInsightUtil.java @@ -23,7 +23,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.PsiRecursiveElementVisitor; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.util.PsiElementFilter; import com.intellij.psi.util.PsiTreeUtil; @@ -125,7 +125,7 @@ public class XsltCodeInsightUtil { public static TextRange getRangeInsideHostingFile(XPathElement expr) { final PsiLanguageInjectionHost host = PsiTreeUtil.getContextOfType(expr, PsiLanguageInjectionHost.class, true); assert host != null; - final List> psi = InjectedLanguageFacadeImpl.getInstance().getInjectedPsiFiles(host); + final List> psi = InjectedLanguageUtil.getInstance().getInjectedPsiFiles(host); assert psi != null; for (Pair pair : psi) { if (PsiTreeUtil.isAncestor(pair.first, expr, false)) { @@ -140,7 +140,7 @@ public class XsltCodeInsightUtil { public static TextRange getRangeInsideHost(XPathElement expr) { final PsiLanguageInjectionHost host = PsiTreeUtil.getContextOfType(expr, PsiLanguageInjectionHost.class, true); assert host != null; - final List> psi = InjectedLanguageFacadeImpl.getInstance().getInjectedPsiFiles(host); + final List> psi = InjectedLanguageUtil.getInstance().getInjectedPsiFiles(host); assert psi != null; for (Pair pair : psi) { if (PsiTreeUtil.isAncestor(pair.first, expr, false)) { diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltXmlAnnotator.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltXmlAnnotator.java index 236012e7e968..444410b9d045 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltXmlAnnotator.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltXmlAnnotator.java @@ -21,7 +21,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.psi.XmlElementVisitor; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import org.intellij.lang.xpath.XPathFile; @@ -49,7 +49,7 @@ public class XsltXmlAnnotator extends XmlElementVisitor implements Annotator { if (s == null || s.length() == 0) { final PsiElement parent = value.getParent(); if (parent instanceof XmlAttribute && XsltSupport.isXPathAttribute((XmlAttribute)parent)) { - InjectedLanguageFacadeImpl.enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() { + InjectedLanguageUtil.enumerate(value, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { if (injectedPsi instanceof XPathFile) { diff --git a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/Xslt2RefactoringTest.java b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/Xslt2RefactoringTest.java index 2d65472b76d5..4f27becf8d88 100644 --- a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/Xslt2RefactoringTest.java +++ b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/Xslt2RefactoringTest.java @@ -22,7 +22,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.formatter.xml.XmlCodeStyleSettings; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.intellij.lang.xpath.TestBase; import org.intellij.lang.xpath.psi.XPathExpression; import org.intellij.lang.xpath.xslt.refactoring.RefactoringOptions; @@ -77,8 +77,8 @@ public class Xslt2RefactoringTest extends TestBase { } }; - final PsiFile file = InjectedLanguageFacadeImpl.findInjectedPsiNoCommit(myFixture.getFile(), editor.getCaretModel().getOffset()); - final Editor editorWindow = InjectedLanguageFacadeImpl.getInjectedEditorForInjectedFile(editor, file); + final PsiFile file = InjectedLanguageUtil.findInjectedPsiNoCommit(myFixture.getFile(), editor.getCaretModel().getOffset()); + final Editor editorWindow = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, file); assertTrue(editorWindow instanceof EditorWindow); action.invoke(myFixture.getProject(), editorWindow, file, null); diff --git a/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/after.java.template b/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/after.java.template new file mode 100644 index 000000000000..52c72cfd5452 --- /dev/null +++ b/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/after.java.template @@ -0,0 +1,3 @@ +String s = "Hello,\n\r" + + "world\n" + + "!\n"; \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/before.java.template b/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/before.java.template new file mode 100644 index 000000000000..0649294d2073 --- /dev/null +++ b/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/before.java.template @@ -0,0 +1 @@ +String s = "Hello,\n\rworld\n!\n"; \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/description.html b/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/description.html new file mode 100644 index 000000000000..9b7858e97f67 --- /dev/null +++ b/resources-en/src/intentionDescriptions/BreakStringOnLineBreaksIntentionAction/description.html @@ -0,0 +1,5 @@ + + +This intention allows to break line on '\n' and '\n\r' line break symbols. + + diff --git a/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/after.java.template b/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/after.java.template new file mode 100644 index 000000000000..c96256042b95 --- /dev/null +++ b/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/after.java.template @@ -0,0 +1,3 @@ +class UiControl { + public static final Color COLOR = new Color(0x64788c); +} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/before.java.template b/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/before.java.template new file mode 100644 index 000000000000..5648c0c0d891 --- /dev/null +++ b/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/before.java.template @@ -0,0 +1,3 @@ +class UiControl { + public static final Color COLOR = new Color(100, 120, 140); +} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/description.html b/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/description.html new file mode 100644 index 000000000000..ba5ea54635bb --- /dev/null +++ b/resources-en/src/intentionDescriptions/ConvertColorRepresentationIntentionAction/description.html @@ -0,0 +1,5 @@ + + +This intention allows to convert between new Color(int rgb) and new Color(int r, int g, int b) constructor variants. + + diff --git a/resources-en/src/messages/CompletionBundle.properties b/resources-en/src/messages/CompletionBundle.properties index dd0b8d250c30..dfa4ba885371 100644 --- a/resources-en/src/messages/CompletionBundle.properties +++ b/resources-en/src/messages/CompletionBundle.properties @@ -6,5 +6,5 @@ completion.smart.hint=Press {0} to show only variants that are suitable by type completion.smart.chain.hint=Press {0} once more to search across chained method calls completion.smart.toar.hint=Press {0} once more to find collections of {1} completion.smart.aslist.hint=Press {0} once more to find arrays of {1} -completion.class.name.hint=Press {0} to view all accessible classes +completion.class.name.hint=Press {0} again to view all accessible classes completion.class.name.hint.2=Press {0} once more to ignore module dependencies while searching \ No newline at end of file diff --git a/resources-en/src/tips/ClassNameCompletion.html b/resources-en/src/tips/ClassNameCompletion.html deleted file mode 100644 index d31a84054ed6..000000000000 --- a/resources-en/src/tips/ClassNameCompletion.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - -

A special variant of the CodeCompletion feature invoked by &shortcut:ClassNameCompletion; allows you to complete the name of any - class no matter if it was imported in the current file or not. If the class is not imported yet the import statement is generated automatically.

-

- - - - - diff --git a/resources-en/src/tips/CompletionImportStatic.html b/resources-en/src/tips/CompletionImportStatic.html index 87a7e4f05a63..8141021f87d9 100644 --- a/resources-en/src/tips/CompletionImportStatic.html +++ b/resources-en/src/tips/CompletionImportStatic.html @@ -7,8 +7,8 @@ To quickly complete a method call of a static method located anywhere in your project, libraries or JDK, enter a prefix - and press &shortcut:ClassNameCompletion;. You'll see all the matching methods. If you want the method you chose to be imported statically, - press &shortcut:EditorRight; and see what happens: + and press &shortcut:CodeCompletion; twice. You'll see all the matching methods. If you want the method you chose to be imported statically, + press &shortcut:ShowIntentionActions; and see what happens:

diff --git a/resources-en/src/tips/SecondClassNameCompletion.html b/resources-en/src/tips/SecondClassNameCompletion.html deleted file mode 100644 index dc08487907fd..000000000000 --- a/resources-en/src/tips/SecondClassNameCompletion.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -

- Pressing the same shortcut after you have invoked Class Name Completion will search for - classes in whole project and its libraries ignoring module dependencies.

-

-

-

-

- - diff --git a/resources-en/src/tips/SmartTypeAnonymous.html b/resources-en/src/tips/SmartTypeAnonymous.html deleted file mode 100644 index 3a52ea323c9a..000000000000 --- a/resources-en/src/tips/SmartTypeAnonymous.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - -

It's very easy to generate the whole anonymous implementation of some interface, for example, of some listener, - by using the SmartType code completion. For example, type

-
-Component component;
-component.addMouseListener(
-    new <caret is here> );
-
-

and press &shortcut:SmartTypeCompletion; to see what happens.

- - - diff --git a/resources-en/src/tips/images/class_name_completion.gif b/resources-en/src/tips/images/class_name_completion.gif deleted file mode 100644 index 673943b0729a..000000000000 Binary files a/resources-en/src/tips/images/class_name_completion.gif and /dev/null differ diff --git a/resources-en/src/tips/images/second_class_name_completion.png b/resources-en/src/tips/images/second_class_name_completion.png deleted file mode 100644 index d01936157d35..000000000000 Binary files a/resources-en/src/tips/images/second_class_name_completion.png and /dev/null differ diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 171a4b03001d..71164c9ec776 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -242,7 +242,7 @@ + id="javaGlobalMemberName"/> @@ -704,6 +704,11 @@ Declaration + + com.intellij.codeInsight.intention.impl.ConvertColorRepresentationIntentionAction + Declaration + + com.intellij.codeInsight.intention.impl.ConvertAbsolutePathToRelativeIntentionAction Other @@ -719,6 +724,12 @@ Other + + com.intellij.codeInsight.intention.impl.BreakStringOnLineBreaksIntentionAction + Other + + + diff --git a/resources/src/ProductivityFeaturesRegistry.xml b/resources/src/ProductivityFeaturesRegistry.xml index e82c1b6dfd47..0f5e00769906 100644 --- a/resources/src/ProductivityFeaturesRegistry.xml +++ b/resources/src/ProductivityFeaturesRegistry.xml @@ -93,24 +93,12 @@ min-usage-count="15" first-show="1" successive-show="3"/> - - - - - - - - > getInjectedPsi() { - return InjectedLanguageFacadeImpl.getInstance().getInjectedPsiFiles(this); + return InjectedLanguageUtil.getInstance().getInjectedPsiFiles(this); } public TextRange getCDATAInterior() { @@ -520,6 +520,6 @@ public class XmlTextImpl extends XmlElementImpl implements XmlText, PsiLanguageI return new XmlTextLiteralEscaper(this); } public void processInjectedPsi(@NotNull InjectedPsiVisitor visitor) { - InjectedLanguageFacadeImpl.enumerate(this, visitor); + InjectedLanguageUtil.enumerate(this, visitor); } } diff --git a/xml/impl/src/com/intellij/xml/util/HtmlUtil.java b/xml/impl/src/com/intellij/xml/util/HtmlUtil.java index 1e8fb921b9c9..27207f7d8178 100644 --- a/xml/impl/src/com/intellij/xml/util/HtmlUtil.java +++ b/xml/impl/src/com/intellij/xml/util/HtmlUtil.java @@ -38,7 +38,7 @@ import com.intellij.psi.html.HtmlTag; import com.intellij.psi.impl.source.html.HtmlDocumentImpl; import com.intellij.psi.impl.source.parsing.xml.HtmlBuilderDriver; import com.intellij.psi.impl.source.parsing.xml.XmlBuilder; -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageFacadeImpl; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.impl.source.xml.XmlAttributeImpl; import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider; import com.intellij.psi.templateLanguages.TemplateLanguageUtil; @@ -471,7 +471,7 @@ public class HtmlUtil { for (final XmlText text : texts) { for (PsiElement _element : text.getChildren()) { if (_element instanceof PsiLanguageInjectionHost) { - InjectedLanguageFacadeImpl.enumerate(_element, injectedPsiVisitor); + InjectedLanguageUtil.enumerate(_element, injectedPsiVisitor); } } } @@ -481,7 +481,7 @@ public class HtmlUtil { if (comments != null && comments.length > 0) { for (final XmlComment comment : comments) { if (comment instanceof PsiLanguageInjectionHost) { - InjectedLanguageFacadeImpl.enumerate(comment, injectedPsiVisitor); + InjectedLanguageUtil.enumerate(comment, injectedPsiVisitor); } } }