diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh index 19932d440338..28b37bd39950 100755 --- a/bin/scripts/unix/idea.sh +++ b/bin/scripts/unix/idea.sh @@ -151,7 +151,7 @@ if [ "$IS_EAP" = "true" ]; then OS_NAME=`echo $OS_TYPE | "$TR" '[:upper:]' '[:lower:]'` AGENT_LIB="yjpagent-$OS_NAME$BITS" if [ -r "$IDE_BIN_HOME/lib$AGENT_LIB.so" ]; then - AGENT="-agentlib:$AGENT_LIB=disablej2ee,disablealloc,delay=10000,sessionname=@@system_selector@@" + AGENT="-agentlib:$AGENT_LIB=disablealloc,delay=10000,sessionname=@@system_selector@@" fi fi diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 7421c91f9cc5..12a2a523c743 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -784,6 +784,8 @@ binding.setVariable("buildMacZip", { String zipRoot, String zipPath, List paths, exclude(name: "bin/fsnotifier") exclude(name: "bin/restarter") exclude(name: "MacOS/*") + exclude(name: "build.txt") + exclude(name: "NOTICE.txt") extraBins.each { exclude(name: it) } @@ -804,6 +806,13 @@ binding.setVariable("buildMacZip", { String zipRoot, String zipPath, List paths, } } + allPaths.each { + zipfileset(dir: it, prefix: "$zipRoot/Resources") { + include(name: "build.txt") + include(name: "NOTICE.txt") + } + } + zipfileset(file: "$macPath/bin/idea.properties", prefix: "$zipRoot/bin") } }) diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java index 4edda91e2dd6..fc3cf13b92db 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -142,11 +142,11 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements Element state = new Element("state"); XmlSerializer.serializeInto(myState, state, new SkipDefaultValuesSerializationFilters() { @Override - protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { if (myState.compilerWasSpecified && "DEFAULT_COMPILER".equals(accessor.getName())) { return true; } - return super.accepts(accessor, bean, beanValue); + return super.accepts(accessor, bean); } }); 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 9ceffac57eb4..ceeef8a6c781 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -93,6 +93,7 @@ import io.netty.handler.codec.protobuf.ProtobufDecoder; import io.netty.handler.codec.protobuf.ProtobufEncoder; import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; +import io.netty.util.internal.ThreadLocalRandom; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.ide.PooledThreadExecutor; @@ -999,6 +1000,9 @@ public class BuildManager implements ApplicationComponent{ cmdLine.addParameter("-Didea.case.sensitive.fs=" + isFSCaseSensitive); } + // this will make netty initialization faster on some systems + cmdLine.addParameter("-Dio.netty.initialSeedUniquifier=" + ThreadLocalRandom.getInitialSeedUniquifier()); + boolean isProfilingMode = false; final String additionalOptions = config.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS; if (!StringUtil.isEmpty(additionalOptions)) { @@ -1013,7 +1017,7 @@ public class BuildManager implements ApplicationComponent{ } if (isProfilingMode) { - cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild"); + cmdLine.addParameter("-agentlib:yjpagent=disablealloc,delay=10000,sessionname=ExternalBuild"); } // debugging diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java b/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java index 4868321f9ca2..9d34478d9e53 100644 --- a/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java +++ b/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -29,13 +29,11 @@ import com.intellij.lang.annotation.AnnotationSession; import com.intellij.lang.annotation.ExternalAnnotator; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.application.ReadActionProcessor; -import com.intellij.openapi.application.Result; import com.intellij.openapi.compiler.*; import com.intellij.openapi.compiler.options.ExcludesConfiguration; import com.intellij.openapi.editor.Document; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; @@ -143,41 +141,41 @@ public class InspectionValidatorWrapper implements Validator { return ProcessingItem.EMPTY_ARRAY; } final ExcludesConfiguration excludesConfiguration = ValidationConfiguration.getExcludedEntriesConfiguration(project); - final List items = new ReadAction>() { - @Override - protected void run(final Result> result) { - final CompileScope compileScope = context.getCompileScope(); - if (!myValidator.isAvailableOnScope(compileScope)) return; + final List items = + DumbService.getInstance(project).runReadActionInSmartMode(new Computable>() { + @Override + public List compute() { + final CompileScope compileScope = context.getCompileScope(); + if (!myValidator.isAvailableOnScope(compileScope)) return null; - final ArrayList items = new ArrayList(); + final ArrayList items = new ArrayList(); - final Processor processor = new ReadActionProcessor() { - @Override - public boolean processInReadAction(VirtualFile file) { - if (!file.isValid()) { - return true; - } - - if (myCompilerManager.isExcludedFromCompilation(file) || - excludesConfiguration.isExcluded(file)) { - return true; - } - - final Module module = context.getModuleByFile(file); - if (module != null) { - final PsiFile psiFile = myPsiManager.findFile(file); - if (psiFile != null) { - items.add(new MyValidatorProcessingItem(psiFile)); + final Processor processor = new Processor() { + @Override + public boolean process(VirtualFile file) { + if (!file.isValid()) { + return true; } - } - return true; - } - }; - ContainerUtil.process(myValidator.getFilesToProcess(myPsiManager.getProject(), context), processor); - result.setResult(items); - } - }.execute().getResultObject(); + if (myCompilerManager.isExcludedFromCompilation(file) || + excludesConfiguration.isExcluded(file)) { + return true; + } + + final Module module = context.getModuleByFile(file); + if (module != null) { + final PsiFile psiFile = myPsiManager.findFile(file); + if (psiFile != null) { + items.add(new MyValidatorProcessingItem(psiFile)); + } + } + return true; + } + }; + ContainerUtil.process(myValidator.getFilesToProcess(myPsiManager.getProject(), context), processor); + return items; + } + }); if (items == null) return ProcessingItem.EMPTY_ARRAY; return items.toArray(new ProcessingItem[items.size()]); diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java deleted file mode 100644 index 1d6ed15abb59..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java +++ /dev/null @@ -1,34 +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.debugger.actions; - -import com.intellij.debugger.impl.DebuggerContextImpl; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.diff.DiffDialogHints; -import com.intellij.diff.DiffManager; -import com.intellij.diff.DiffRequestFactory; -import com.intellij.diff.requests.DiffRequest; -import com.intellij.openapi.project.Project; - -/** - * @author Jeka - */ -public class CompareValueWithClipboardAction extends BaseValueAction { - protected void processText(final Project project, final String text, DebuggerTreeNodeImpl node, DebuggerContextImpl debuggerContext) { - DiffRequest request = DiffRequestFactory.getInstance().createClipboardVsValue(text); - DiffManager.getInstance().showDiff(project, request); - } -} \ No newline at end of file diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CopyValueAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CopyValueAction.java deleted file mode 100644 index 256566557ae1..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/CopyValueAction.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.impl.DebuggerContextImpl; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.openapi.ide.CopyPasteManager; -import com.intellij.openapi.project.Project; - -import java.awt.datatransfer.StringSelection; - -/* - * @author Jeka - */ -public class CopyValueAction extends BaseValueAction { - protected void processText(final Project project, final String text, DebuggerTreeNodeImpl node, DebuggerContextImpl debuggerContext) { - CopyPasteManager.getInstance().setContents(new StringSelection(text)); - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/EditWatchAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/EditWatchAction.java deleted file mode 100644 index 48bf5acd10bb..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/EditWatchAction.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.ui.DebuggerPanelsManager; -import com.intellij.debugger.ui.impl.MainWatchPanel; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.project.Project; - -/** - * User: lex - * Date: Sep 26, 2003 - * Time: 8:34:01 PM - */ -public class EditWatchAction extends DebuggerAction { - public void actionPerformed(final AnActionEvent e) { - final DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); - if(selectedNode == null || !(selectedNode.getDescriptor() instanceof WatchItemDescriptor)) return; - - Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); - - MainWatchPanel watchPanel = DebuggerPanelsManager.getInstance(project).getWatchPanel(); - if(watchPanel != null) { - watchPanel.editNode(selectedNode); - } - } - - public void update(AnActionEvent e) { - final DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); - - e.getPresentation().setVisible(selectedNode != null && selectedNode.getDescriptor() instanceof WatchItemDescriptor); - } - -}; diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/NewWatchAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/NewWatchAction.java deleted file mode 100644 index 6a8d3fe017df..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/NewWatchAction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Class NewWatchAction - * @author Jeka - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.ui.DebuggerPanelsManager; -import com.intellij.debugger.ui.impl.MainWatchPanel; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - -public class NewWatchAction extends DebuggerAction { - public void actionPerformed(final AnActionEvent e) { - getWatchPanel(e).newWatch(); - } - - @Override - public void update(@NotNull AnActionEvent e) { - e.getPresentation().setEnabled(getWatchPanel(e) != null); - } - - private static MainWatchPanel getWatchPanel(AnActionEvent e) { - Project project = e.getProject(); - return project != null ? DebuggerPanelsManager.getInstance(project).getWatchPanel() : null; - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveAllWatchesAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/RemoveAllWatchesAction.java deleted file mode 100644 index e6773227cc1c..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveAllWatchesAction.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.ui.impl.watch.DebuggerTree; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.Presentation; - -import java.util.Enumeration; - -/** - * User: lex - * Date: Sep 26, 2003 - * Time: 6:24:44 PM - */ -public class RemoveAllWatchesAction extends RemoveWatchAction { - protected DebuggerTreeNodeImpl[] getNodesToDelete(AnActionEvent e) { - DebuggerTree tree = getTree(e.getDataContext()); - if(tree == null) return null; - DebuggerTreeNodeImpl root = (DebuggerTreeNodeImpl)tree.getModel().getRoot(); - DebuggerTreeNodeImpl [] result = new DebuggerTreeNodeImpl[root.getChildCount()]; - int i = 0; - for(Enumeration enumeration = root.children(); enumeration.hasMoreElements(); i++) { - DebuggerTreeNodeImpl node = (DebuggerTreeNodeImpl)enumeration.nextElement(); - result[i] = node; - } - return result; - } - - protected void updatePresentation(Presentation presentation, int watchesCount) { - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveWatchAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/RemoveWatchAction.java deleted file mode 100644 index 322241943357..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveWatchAction.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.ui.impl.MainWatchPanel; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor; -import com.intellij.debugger.DebuggerBundle; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.Presentation; - -import java.util.ArrayList; - -public class RemoveWatchAction extends DebuggerAction { - protected DebuggerTreeNodeImpl[] getNodesToDelete(AnActionEvent e) { - DebuggerTreeNodeImpl[] selectedNodes = getSelectedNodes(e.getDataContext()); - if(selectedNodes == null) return null; - ArrayList selectedWatches = new ArrayList(); - for (int i = 0; i < selectedNodes.length; i++) { - if(selectedNodes[i].getDescriptor() instanceof WatchItemDescriptor) { - selectedWatches.add(selectedNodes[i]); - } - } - - return selectedWatches.toArray(new DebuggerTreeNodeImpl[selectedWatches.size()]); - } - - public void actionPerformed(AnActionEvent e) { - DebuggerTreeNodeImpl [] nodes = getNodesToDelete(e); - if (nodes == null || nodes.length == 0) return; - - MainWatchPanel watchPanel = (MainWatchPanel)getPanel(e.getDataContext()); - - for (int i = 0; i < nodes.length; i++) { - DebuggerTreeNodeImpl node = nodes[i]; - watchPanel.getWatchTree().removeWatch(node); - } - } - - protected void updatePresentation(Presentation presentation, int watchesCount) { - presentation.setText(DebuggerBundle.message("action.remove.watch.text", watchesCount)); - } - - public void update(AnActionEvent event) { - Presentation presentation = event.getPresentation(); - DebuggerTreeNodeImpl[] nodes = getNodesToDelete(event); - if (nodes != null && nodes.length > 0) { - presentation.setEnabled(true); - } - else { - presentation.setEnabled(false); - } - updatePresentation(presentation, nodes != null? nodes.length : 0); - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ShowExecutionPointActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/ShowExecutionPointActionHandler.java deleted file mode 100644 index f80bab05b6ad..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ShowExecutionPointActionHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.DebuggerManagerEx; -import com.intellij.debugger.impl.DebuggerSession; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.Project; -import com.intellij.xdebugger.impl.actions.DebuggerActionHandler; -import org.jetbrains.annotations.NotNull; - -public class ShowExecutionPointActionHandler extends DebuggerActionHandler { - public void perform(@NotNull final Project project, final AnActionEvent event) { - final DebuggerSession session = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession(); - if (session != null) { - session.showExecutionPoint(); - } - } - - public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) { - DebuggerSession debuggerSession = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession(); - return debuggerSession != null && debuggerSession.isPaused() && - debuggerSession.getContextManager().getContext().getSuspendContext().getThread() != null; - } -} \ No newline at end of file diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java index 972cfef48661..6c53669dd810 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.xdebugger.impl.XDebuggerUtilImpl; +import org.jetbrains.annotations.NotNull; /** * @author egor @@ -36,10 +37,10 @@ public class ShowLibraryFramesAction extends ToggleAction { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean shouldShow = !(Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean shouldShow = !Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(shouldShow ? ourTextWhenShowIsOn : ourTextWhenShowIsOff); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 29a2c3414695..09c869db99c5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -1098,7 +1098,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb throw (RuntimeException)exception[0]; } else { - LOG.assertTrue(false); + LOG.error("Unexpected exception " + exception[0]); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java index 0b1cd18bb05b..5dd4279b3cd1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java @@ -137,11 +137,7 @@ public class JavaDebugProcess extends XDebugProcess { myNodeManager = new NodeManagerImpl(session.getProject(), null) { @Override public DebuggerTreeNodeImpl createNode(final NodeDescriptor descriptor, EvaluationContext evaluationContext) { - // value gathered here is required for correct renderers work. e.g. array renderer - //((NodeDescriptorImpl)descriptor).setContext((EvaluationContextImpl)evaluationContext); - final DebuggerTreeNodeImpl node = new DebuggerTreeNodeImpl(null, descriptor); - //((NodeDescriptorImpl)descriptor).updateRepresentation((EvaluationContextImpl)evaluationContext, DescriptorLabelListener.DUMMY_LISTENER); - return node; + return new DebuggerTreeNodeImpl(null, descriptor); } @Override @@ -322,7 +318,6 @@ public class JavaDebugProcess extends XDebugProcess { public void registerAdditionalActions(@NotNull DefaultActionGroup leftToolbar, @NotNull DefaultActionGroup topToolbar, @NotNull DefaultActionGroup settings) { Constraints beforeRunner = new Constraints(Anchor.BEFORE, "Runner.Layout"); leftToolbar.add(Separator.getInstance(), beforeRunner); - //leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.EXPORT_THREADS), beforeRunner); leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.DUMP_THREADS), beforeRunner); leftToolbar.add(Separator.getInstance(), beforeRunner); @@ -339,10 +334,10 @@ public class JavaDebugProcess extends XDebugProcess { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean autoModeEnabled = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean autoModeEnabled = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(autoModeEnabled ? "All-Variables Mode" : "Auto-Variables Mode"); } @@ -374,10 +369,10 @@ public class JavaDebugProcess extends XDebugProcess { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean watchValues = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean watchValues = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); DebugProcessImpl process = getCurrentDebugProcess(e.getProject()); final String actionText = watchValues ? myMyTextDisable : myTextEnable; if (process == null || process.canGetMethodReturnValue()) { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java index e4905af7fec5..196995a25013 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java @@ -46,4 +46,9 @@ public class DisableGC implements Evaluator{ public Modifier getModifier() { return myDelegate.getModifier(); } + + @Override + public String toString() { + return "NoGC -> " + myDelegate; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index 2363cf9f93ba..8779d9f94b91 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -952,11 +952,10 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } if (qualifier instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifier).resolve() instanceof PsiClass) { - // this is a call to a 'static' method - if (contextClass == null && type == null) { - throwEvaluateException(DebuggerBundle.message("evaluation.error.qualifier.type.unknown", qualifier.getText())); + // this is a call to a 'static' method but class is not available, try to evaluate by qname + if (contextClass == null) { + contextClass = JVMNameUtil.getJVMRawText(((PsiReferenceExpression)qualifier).getQualifiedName()); } - assert contextClass != null; objectEvaluator = new TypeEvaluator(contextClass); } else { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java index 2f4b85d22609..4597167d9c99 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -66,4 +66,9 @@ class LiteralEvaluator implements Evaluator { throw EvaluateExceptionUtil .createEvaluateException(DebuggerBundle.message("evaluation.error.unknown.expression.type", myExpectedType)); } + + @Override + public String toString() { + return myValue.toString(); + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java index b02ec96fad31..caf0e41c07c3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -156,4 +156,9 @@ class LocalVariableEvaluator implements Evaluator { } return modifier; } + + @Override + public String toString() { + return myLocalVariableName; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java index d495f3d19d08..3aff8225622f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java @@ -211,4 +211,9 @@ public class MethodEvaluator implements Evaluator { } return null; } + + @Override + public String toString() { + return "call " + myMethodName; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java b/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java index d084c0308b72..cc0a18951971 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -84,6 +84,21 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy { throw new EvaluateException(error.getMessage(), error); } + @Override + public boolean isValid() { + if (!super.isValid()) { + return false; + } + try { + if (myStackFrame != null) { + myStackFrame.location(); //extra check if jdi frame is valid + } + return true; + } catch (InvalidStackFrameException e) { + return false; + } + } + @Override protected void clearCaches() { DebuggerManagerThreadImpl.assertIsManagerThread(); diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java index 2855ab4dfc1f..7d654d621549 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java @@ -35,10 +35,8 @@ import java.util.Map; @State( name = "DebuggerSettings", - storages = { - @Storage( - file = StoragePathMacros.APP_CONFIG + "/other.xml" - )} + defaultStateAsResource = true, + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") ) public class DebuggerSettings implements Cloneable, PersistentStateComponent { private static final Logger LOG = Logger.getInstance(DebuggerSettings.class); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java index a088e953557f..51a96197ba48 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java @@ -287,7 +287,6 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos } leftToolbar.addSeparator(); - //addAction(leftToolbar, DebuggerActions.EXPORT_THREADS); addAction(leftToolbar, DebuggerActions.DUMP_THREADS); leftToolbar.addSeparator(); @@ -523,10 +522,10 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean autoModeEnabled = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean autoModeEnabled = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(autoModeEnabled ? "All-Variables Mode" : "Auto-Variables Mode"); } @@ -558,10 +557,10 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean watchValues = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean watchValues = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); final DebugProcessImpl process = getDebugProcess(); final String actionText = watchValues ? myMyTextDisable : myTextEnable; if (process != null && process.canGetMethodReturnValue()) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java index e17b8af10827..dba4453ae43c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -710,10 +710,10 @@ public class FramesPanel extends UpdatableDebuggerView implements DataProvider { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean shouldShow = !(Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean shouldShow = !Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(shouldShow ? ourTextWhenShowIsOn : ourTextWhenShowIsOff); } diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java index fc13858daac9..d10b656ad6a8 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java +++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java @@ -307,7 +307,10 @@ public abstract class SourcePosition implements Navigatable{ } public static SourcePosition createFromElement(PsiElement element) { - final PsiElement navigationElement = element.getNavigationElement(); + ApplicationManager.getApplication().assertReadAccessAllowed(); + PsiElement navigationElement = element.getNavigationElement(); + final SmartPsiElementPointer pointer = + SmartPointerManager.getInstance(navigationElement.getProject()).createSmartPsiElementPointer(navigationElement); final PsiFile psiFile; if (JspPsiUtil.isInJspFile(navigationElement)) { psiFile = JspPsiUtil.getJspFile(navigationElement); @@ -318,12 +321,19 @@ public abstract class SourcePosition implements Navigatable{ return new SourcePositionCache(psiFile) { @Override protected PsiElement calcPsiElement() { - return navigationElement; + ApplicationManager.getApplication().assertReadAccessAllowed(); + return pointer.getElement(); } @Override protected int calcOffset() { - return navigationElement.getTextOffset(); + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Integer compute() { + PsiElement elem = pointer.getElement(); + return elem != null ? elem.getTextOffset() : -1; + } + }); } }; } diff --git a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java index c6bb1f199b0e..be42dd7fbf8b 100644 --- a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java +++ b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java @@ -67,7 +67,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider { @NotNull @Override public Collection getActions(List orderEntries, final PsiFile psiFile) { - VirtualFile jar = getJarByPsiFile(psiFile); + final VirtualFile jar = getJarByPsiFile(psiFile); if (jar == null) return Collections.emptyList(); final String jarName = jar.getNameWithoutExtension(); @@ -145,7 +145,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider { SourceSearcher[] searchers = {new MavenCentralSourceSearcher(), new SonatypeSourceSearcher()}; for (SourceSearcher searcher : searchers) { try { - artifactUrl = searcher.findSourceJar(indicator, artifactId, version); + artifactUrl = searcher.findSourceJar(indicator, artifactId, version, jar); } catch (SourceSearchException e) { LOG.warn(e); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java index 87867565f63a..466903efaf30 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java @@ -86,20 +86,20 @@ public class IncreaseLanguageLevelFix implements IntentionAction { LOG.assertTrue(virtualFile != null); final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project); final LanguageLevel moduleLevel = module == null ? null : LanguageLevelModuleExtensionImpl.getInstance(module).getLanguageLevel(); - if (moduleLevel != null && isLanguageLevelAcceptable(project, module, myLevel)) { - final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel(); - rootModel.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLevel); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + if (moduleLevel != null && isLanguageLevelAcceptable(project, module, myLevel)) { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel(); + rootModel.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLevel); rootModel.commit(); } - }); - } - else { - LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(myLevel); - ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(EmptyRunnable.INSTANCE, false, true); - } + else { + LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(myLevel); + ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(EmptyRunnable.INSTANCE, false, true); + } + } + }); } @Nullable diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java index dc392cec131b..eb9f162a909d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java @@ -263,13 +263,14 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp if (element instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element; - final PsiMethod psiMethod = methodCall.resolveMethod(); + JavaResolveResult result = methodCall.resolveMethodGenerics(); + final PsiMethod psiMethod = (PsiMethod)result.getElement(); if (psiMethod == null) { return null; } final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); - final String qualifierByMethodCall = getQualifierTextByMethodCall(methodCall, functionalInterfaceType, parameters, psiMethod); + final String qualifierByMethodCall = getQualifierTextByMethodCall(methodCall, functionalInterfaceType, parameters, psiMethod, result.getSubstitutor()); if (qualifierByMethodCall != null) { return qualifierByMethodCall + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodExpression.getReferenceName(); } @@ -324,7 +325,8 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp private static String getQualifierTextByMethodCall(final PsiMethodCallExpression methodCall, final PsiType functionalInterfaceType, final PsiParameter[] parameters, - final PsiMethod psiMethod) { + final PsiMethod psiMethod, + final PsiSubstitutor substitutor) { final PsiExpression qualifierExpression = methodCall.getMethodExpression().getQualifierExpression(); @@ -332,7 +334,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp LOG.assertTrue(containingClass != null); if (qualifierExpression != null) { - boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, psiMethod); + boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(PsiMethodReferenceUtil.getFirstParameterType(functionalInterfaceType, methodCall), containingClass, substitutor); return isReceiverType ? composeReceiverQualifierText(parameters, psiMethod, containingClass, qualifierExpression) : qualifierExpression.getText(); } @@ -422,7 +424,6 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp if (lambdaExpression == null) return; PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType(); if (functionalInterfaceType == null || !functionalInterfaceType.isValid()) return; - String functionalTypeText = functionalInterfaceType.getCanonicalText(); final String methodRefText = createMethodReferenceText(element, functionalInterfaceType, lambdaExpression.getParameterList().getParameters()); diff --git a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java index 65c6777bcbbb..e4103ce1a9c9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java @@ -106,7 +106,7 @@ public class CodeInsightUtil { if (parent == null) return PsiElement.EMPTY_ARRAY; while (true) { if (parent instanceof PsiStatement) { - if (!(element1 instanceof PsiComment || element2 instanceof PsiComment)) { + if (!(element1 instanceof PsiComment)) { parent = parent.getParent(); } break; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index d36c35ca6e73..90e550a75b30 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -37,9 +37,11 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.Consumer; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Set; import static com.intellij.patterns.PsiJavaPatterns.psiClass; import static com.intellij.patterns.PsiJavaPatterns.psiElement; @@ -117,26 +119,52 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { final boolean pkgContext = JavaCompletionUtil.inSomePackage(insertedElement); AllClassesGetter.processJavaClasses(parameters, matcher, filterByScope, new Consumer() { - @Override - public void consume(PsiClass psiClass) { - if (filter.isAcceptable(psiClass, insertedElement)) { - if (!inJavaContext) { - consumer.consume(AllClassesGetter.createLookupItem(psiClass, AllClassesGetter.TRY_SHORTENING)); - } else { - for (JavaPsiClassReferenceElement element : createClassLookupItems(psiClass, afterNew, - JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER, new Condition() { + @Override + public void consume(PsiClass psiClass) { + processClass(psiClass, ContainerUtil.newHashSet(), ""); + } + + private void processClass(PsiClass psiClass, Set visited, String prefix) { + if (!visited.add(psiClass)) return; + + boolean isInnerClass = StringUtil.isNotEmpty(prefix); + if (isInnerClass && isProcessedIndependently(psiClass)) { + return; + } + + if (filter.isAcceptable(psiClass, insertedElement)) { + if (!inJavaContext) { + JavaPsiClassReferenceElement element = AllClassesGetter.createLookupItem(psiClass, AllClassesGetter.TRY_SHORTENING); + element.setLookupString(prefix + element.getLookupString()); + consumer.consume(element); + } else { + for (JavaPsiClassReferenceElement element : createClassLookupItems(psiClass, afterNew, + JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER, new Condition() { @Override public boolean value(PsiClass psiClass) { return filter.isAcceptable(psiClass, insertedElement) && AllClassesGetter.isAcceptableInContext(insertedElement, psiClass, filterByScope, pkgContext); } })) { - consumer.consume(element); - } + element.setLookupString(prefix + element.getLookupString()); + consumer.consume(element); + } + } + } else { + String name = psiClass.getName(); + if (name != null) { + for (PsiClass innerClass : psiClass.getInnerClasses()) { + processClass(innerClass, visited, prefix + name + "."); } } } - }); + } + + private boolean isProcessedIndependently(PsiClass psiClass) { + String innerName = psiClass.getName(); + return innerName != null && matcher.prefixMatches(innerName); + } + }); } static LookupElement highlightIfNeeded(JavaPsiClassReferenceElement element, CompletionParameters parameters) { diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java index 9817ce5e631d..3dca018ab61a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java @@ -664,7 +664,20 @@ public class GenerateMembersUtil { } } result = (PsiMethod)CodeStyleManager.getInstance(project).reformat(result); - PropertyUtil.annotateWithNullableStuff(field, result); + + PsiModifierListOwner listOwner = null; + if (templatesManager instanceof GetterTemplatesManager) { + listOwner = result; + } + else { + final PsiParameter[] parameters = result.getParameterList().getParameters(); + if (parameters.length == 1) { + listOwner = parameters[0]; + } + } + if (listOwner != null) { + PropertyUtil.annotateWithNullableStuff(field, listOwner); + } return generatePrototype(field, result); } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm b/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm index bb6bb906b464..4c1046e4f503 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm +++ b/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm @@ -5,7 +5,7 @@ static void ## #else $classname ## #end -set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($field.name))($field.type $paramName) { +set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($field.type $paramName) { #if ($field.name == $paramName) #if (!$field.modifierStatic) this.## diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm b/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm index b63bfeb33fd8..7482fcfb2a6c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm +++ b/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm @@ -3,7 +3,7 @@ public ## static ## #end $field.type ## -#set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($field.name))) +#set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))) #if ($field.boolean) #if ($StringUtil.startsWithIgnoreCase($name, 'is')) #set($name = $StringUtil.decapitalize($name)) diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm b/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm index 1418987baba0..7a1e2a76100e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm +++ b/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm @@ -3,7 +3,7 @@ public ## #if($field.modifierStatic) static ## #end -void set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($field.name))($field.type $paramName) { +void set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($field.type $paramName) { #if ($field.name == $paramName) #if (!$field.modifierStatic) this.## diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java index c8b7da8aed28..e62fa10e4550 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java @@ -40,7 +40,9 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.ui.components.JBList; import com.intellij.util.IncorrectOperationException; @@ -180,7 +182,9 @@ public class ImplementAbstractMethodHandler { ArrayList list = new ArrayList(); for (PsiClass inheritor : ClassInheritorsSearch.search(psiClass, true)) { if (!inheritor.isInterface()) { - PsiMethod method = inheritor.findMethodBySignature(myMethod, true); + final PsiSubstitutor classSubstitutor = TypeConversionUtil.getClassSubstitutor(psiClass, inheritor, PsiSubstitutor.EMPTY); + LOG.assertTrue(classSubstitutor != null); + PsiMethod method = MethodSignatureUtil.findMethodBySignature(inheritor, myMethod.getSignature(classSubstitutor), true); if (method == null || !method.getContainingClass().equals(psiClass)) continue; list.add(inheritor); } diff --git a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java index aeb6c7574a01..7e4ed5639904 100644 --- a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java @@ -2,6 +2,7 @@ package com.intellij.jarFinder; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.xpath.XPath; @@ -21,13 +22,19 @@ public class MavenCentralSourceSearcher extends SourceSearcher { @Override protected String findSourceJar(@NotNull ProgressIndicator indicator, @NotNull String artifactId, - @NotNull String version) throws SourceSearchException { + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { try { indicator.setText("Connecting to https://search.maven.org"); indicator.checkCanceled(); - String url = "https://search.maven.org/solrsearch/select?rows=3&wt=xml&q=a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22"; + String url = "https://search.maven.org/solrsearch/select?rows=3&wt=xml&q="; + final String groupId = findMavenGroupId(classesJar, artifactId); + if (groupId != null) { + url += "g:%22" + groupId + "%22%20AND%20"; + } + url += "a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22"; @SuppressWarnings("unchecked") List artifactList = (List)XPath.newInstance("/response/result/doc/str[@name='g']").selectNodes(readDocumentCancelable(indicator, url)); if (artifactList.isEmpty()) { diff --git a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java index b4251970fc10..76d713055a4a 100644 --- a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java @@ -2,6 +2,7 @@ package com.intellij.jarFinder; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.xpath.XPath; @@ -19,7 +20,10 @@ public class SonatypeSourceSearcher extends SourceSearcher { @Nullable @Override - public String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) + public String findSourceJar(@NotNull final ProgressIndicator indicator, + @NotNull String artifactId, + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { try { indicator.setIndeterminate(true); @@ -28,6 +32,11 @@ public class SonatypeSourceSearcher extends SourceSearcher { indicator.checkCanceled(); String url = "https://oss.sonatype.org/service/local/lucene/search?collapseresults=true&c=sources&a=" + artifactId + "&v=" + version; + String groupId = findMavenGroupId(classesJar, artifactId); + if(groupId != null) { + url += ("&g=" + groupId); + } + List artifactList = (List)XPath.newInstance("/searchNGResponse/data/artifact").selectNodes(readDocumentCancelable(indicator, url)); if (artifactList.isEmpty()) { return null; @@ -50,7 +59,7 @@ public class SonatypeSourceSearcher extends SourceSearcher { return null; } - String groupId = element.getChildTextTrim("groupId"); + groupId = element.getChildTextTrim("groupId"); String repositoryId = artifactHintList.get(0).getChildTextTrim("repositoryId"); return "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=" + diff --git a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java index 3c5d138e2b13..3533f1a4bb21 100644 --- a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java @@ -2,6 +2,10 @@ package com.intellij.jarFinder; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.io.StreamUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.io.HttpRequests; import org.jdom.Document; import org.jdom.JDOMException; @@ -9,19 +13,43 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; /** * @author Sergey Evdokimov */ public abstract class SourceSearcher { + + private static final String MAVEN_POM_ENTRY_PREFIX = "META-INF/maven/"; + /** * @param indicator * @param artifactId * @param version - * @return groupId of found artifact and url. + * @return url of found artifact */ @Nullable - protected abstract String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) throws SourceSearchException; + protected String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) + throws SourceSearchException { + return null; + } + + /** + * @param indicator + * @param artifactId + * @param version + * @param classesJar classes jar + * @return url of found artifact + */ + @Nullable + protected String findSourceJar(@NotNull final ProgressIndicator indicator, + @NotNull String artifactId, + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { + return findSourceJar(indicator, artifactId, version); + } @NotNull protected static Document readDocumentCancelable(final ProgressIndicator indicator, String url) throws IOException { @@ -39,6 +67,34 @@ public abstract class SourceSearcher { } }); } + + @Nullable + protected static String findMavenGroupId(@NotNull VirtualFile classesJar, String artifactId) { + try { + JarFile jarFile = new JarFile(VfsUtilCore.virtualToIoFile(classesJar)); + try { + final Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + final String name = entry.getName(); + if (StringUtil.startsWith(name, MAVEN_POM_ENTRY_PREFIX) && StringUtil.endsWith(name, "/" + artifactId + "/pom.xml")) { + final int index = name.indexOf('/', MAVEN_POM_ENTRY_PREFIX.length()); + return index != -1 ? name.substring(MAVEN_POM_ENTRY_PREFIX.length(), index) : null; + } + } + } + finally { + try { + jarFile.close(); + } + catch (IOException ignore) { + } + } + } + catch (IOException ignore) { + } + return null; + } } class SourceSearchException extends Exception { diff --git a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java index bd2d1a9a29fc..eddd536d19fb 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java @@ -28,6 +28,7 @@ import com.intellij.psi.PsiJavaFile; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author max @@ -44,7 +45,10 @@ public class JavaImportOptimizer implements ImportOptimizer { Project project = file.getProject(); final PsiImportList newImportList = JavaCodeStyleManager.getInstance(project).prepareOptimizeImportsResult((PsiJavaFile)file); if (newImportList == null) return EmptyRunnable.getInstance(); - return new Runnable() { + + return new CollectingInfoRunnable() { + private int myImportListLengthDiff = 0; + @Override public void run() { try { @@ -55,12 +59,23 @@ public class JavaImportOptimizer implements ImportOptimizer { } final PsiImportList oldImportList = ((PsiJavaFile)file).getImportList(); assert oldImportList != null; + int importsBefore = oldImportList.getAllImportStatements().length; oldImportList.replace(newImportList); + myImportListLengthDiff = importsBefore - newImportList.getAllImportStatements().length; } catch (IncorrectOperationException e) { LOG.error(e); } } + + @Nullable + @Override + public String getUserNotificationInfo() { + if (myImportListLengthDiff > 0) { + return "removed " + myImportListLengthDiff + " import" + (myImportListLengthDiff > 1 ? "s" : ""); + } + return null; + } }; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java index 392cacfb2ac9..c93b33068c1b 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java @@ -1,19 +1,34 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.psi.impl.source.resolve.reference.impl.providers; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiPackage; -import com.intellij.psi.impl.source.resolve.reference.impl.providers.PackageReferenceSet; import com.intellij.util.PatternUtil; import com.intellij.util.Processor; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import java.util.regex.Pattern; public class PatternPackageReferenceSet extends PackageReferenceSet { + public PatternPackageReferenceSet(String packageName, PsiElement element, int startInElement) { super(packageName, element, startInElement); } @@ -24,7 +39,7 @@ public class PatternPackageReferenceSet extends PackageReferenceSet { if (packageName.contains("*")) { final Pattern pattern = PatternUtil.fromMask(packageName); - final Set packages = new HashSet(); + final Set packages = new LinkedHashSet(); processSubPackages(context, new Processor() { @Override @@ -39,13 +54,13 @@ public class PatternPackageReferenceSet extends PackageReferenceSet { return packages; } - else { - return super.resolvePackageName(context, packageName); - } + + return super.resolvePackageName(context, packageName); } - protected static boolean processSubPackages(final PsiPackage pkg, final Processor processor) { + protected static boolean processSubPackages(final PsiPackage pkg, final Processor processor) { if (!processor.process(pkg)) return false; + for (final PsiPackage aPackage : pkg.getSubPackages()) { if (!processSubPackages(aPackage, processor)) return false; } diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java index a620938830ef..c07294b60351 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java @@ -203,8 +203,8 @@ public class CreateTestDialog extends DialogWrapper { }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK)), myTargetPackageField.getChildComponent()); - myGenerateBeforeBox = new JCheckBox("setUp/@Before"); - myGenerateAfterBox = new JCheckBox("tearDown/@After"); + myGenerateBeforeBox = new JCheckBox(CodeInsightBundle.message("intention.create.test.dialog.setUp")); + myGenerateAfterBox = new JCheckBox(CodeInsightBundle.message("intention.create.test.dialog.tearDown")); myShowInheritedMethodsBox = new JCheckBox(CodeInsightBundle.message("intention.create.test.dialog.show.inherited")); myShowInheritedMethodsBox.addActionListener(new ActionListener() { @@ -411,7 +411,9 @@ public class CreateTestDialog extends DialogWrapper { constr.gridy = gridy++; constr.gridx = 0; constr.weightx = 0; - panel.add(new JLabel(CodeInsightBundle.message("intention.create.test.dialog.select.methods")), constr); + final JLabel membersLabel = new JLabel(CodeInsightBundle.message("intention.create.test.dialog.select.methods")); + membersLabel.setLabelFor(myMethodsTable); + panel.add(membersLabel, constr); constr.gridx = 1; constr.weightx = 1; diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index 1fd4e786509f..b9cd4b2a1393 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -30,10 +30,10 @@ public class PsiMethodReferenceUtil { public static final Logger LOG = Logger.getInstance("#" + PsiMethodReferenceUtil.class.getName()); public static boolean hasReceiver(PsiType[] parameterTypes, QualifierResolveResult qualifierResolveResult, PsiMethodReferenceExpression methodRef) { - if (parameterTypes.length > 0 && + if (parameterTypes.length > 0 && !methodRef.isConstructor() && - isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()) && - isStaticallyReferenced(methodRef)) { + isStaticallyReferenced(methodRef) && + isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor())) { return true; } return false; @@ -46,7 +46,7 @@ public class PsiMethodReferenceUtil { LOG.assertTrue(containingClass != null); PsiSubstitutor subst = result.getSubstitutor(); PsiClass qContainingClass = getQualifierResolveResult(expression).getContainingClass(); - if (qContainingClass != null && isReceiverType(functionalInterfaceType, containingClass, (PsiMethod)resolve)) { + if (qContainingClass != null && isReceiverType(getFirstParameterType(functionalInterfaceType, expression), qContainingClass, subst)) { subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); LOG.assertTrue(subst != null); } @@ -202,53 +202,27 @@ public class PsiMethodReferenceUtil { return true; } - public static boolean isReceiverType(@Nullable PsiClass aClass, @Nullable PsiClass containingClass) { - return InheritanceUtil.isInheritorOrSelf(aClass, containingClass, true); - } - - public static boolean isReceiverType(PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) { - if (containingClass != null) { - receiverType = getExpandedType(receiverType, containingClass); + //if P1, ..., Pn is not empty and P1 is a subtype of ReferenceType, then the method reference expression is treated as + // if it were a method invocation expression with argument expressions of types P2, ...,Pn. + public static boolean isReceiverType(@Nullable PsiType receiverType, PsiClass containingClass, PsiSubstitutor psiSubstitutor) { + if (receiverType == null) { + return false; } - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(receiverType); - final PsiClass receiverClass = resolveResult.getElement(); - if (receiverClass != null && isReceiverType(receiverClass, containingClass)) { - if (emptyOrRaw(containingClass, psiSubstitutor)) { - return true; - } - final PsiSubstitutor derivedSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, receiverClass, psiSubstitutor); - return derivedSubstitutor != null && TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, derivedSubstitutor), receiverType); - } - return false; + return TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, psiSubstitutor), + getExpandedType(receiverType, containingClass)); } - private static boolean emptyOrRaw(PsiClass containingClass, PsiSubstitutor psiSubstitutor) { - return PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor) || - psiSubstitutor.getSubstitutionMap().isEmpty(); - } - - public static boolean isReceiverType(PsiType functionalInterfaceType, PsiClass containingClass, @Nullable PsiMethod referencedMethod) { + public static PsiType getFirstParameterType(PsiType functionalInterfaceType, PsiElement context) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final MethodSignature function = LambdaUtil.getFunction(resolveResult.getElement()); if (function != null) { final int interfaceMethodParamsLength = function.getParameterTypes().length; if (interfaceMethodParamsLength > 0) { - final PsiType firstParamType = resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]); - boolean isReceiver = isReceiverType(firstParamType, - containingClass, PsiUtil.resolveGenericsClassInType(firstParamType).getSubstitutor()); - if (isReceiver) { - if (referencedMethod == null){ - if (interfaceMethodParamsLength == 1) return true; - return false; - } - if (referencedMethod.getParameterList().getParametersCount() != interfaceMethodParamsLength - 1) { - return false; - } - return true; - } + PsiType type = resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]); + return type != null ? PsiUtil.captureToplevelWildcards(type, context) : null; } } - return false; + return null; } private static PsiType getExpandedType(PsiType type, @NotNull PsiElement typeElement) { diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java index 063f2b81934e..276fd77f0e3f 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java @@ -312,17 +312,17 @@ public class MethodCandidateInfo extends CandidateInfo{ public static CurrentCandidateProperties getCurrentMethod(PsiElement context) { + if (isOverloadCheck()) { + ourOverloadGuard.prohibitResultCaching(ourOverloadGuard.currentStack().get(0)); + } final Map currentMethodCandidates = CURRENT_CANDIDATE.get(); return currentMethodCandidates != null ? currentMethodCandidates.get(context) : null; } public static void updateSubstitutor(PsiElement context, PsiSubstitutor newSubstitutor) { - final Map currentMethodCandidates = CURRENT_CANDIDATE.get(); - if (currentMethodCandidates != null) { - final CurrentCandidateProperties properties = currentMethodCandidates.get(context); - if (properties != null) { - properties.setSubstitutor(newSubstitutor); - } + CurrentCandidateProperties candidateProperties = getCurrentMethod(context); + if (candidateProperties != null) { + candidateProperties.setSubstitutor(newSubstitutor); } } diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 3213970cc260..1106633efdb0 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -403,6 +403,7 @@ public class TypeConversionUtil { final PsiClass class1 = PsiUtil.resolveClassInType(typeArg1); if (class1 instanceof PsiTypeParameter) { for (PsiType type : class1.getExtendsListTypes()) { + type = substitutor1.substitute(type); if (TypesDistinctProver.provablyDistinct(type, typeArg2) && !isAssignable(type, typeArg2)) return false; } } diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java index 9a3fc135e16f..7d59b98b1fcf 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java @@ -262,7 +262,13 @@ public class TypesDistinctProver { final PsiType boundBound = ((PsiWildcardType)bound).getBound(); if (boundBound != null && !boundBound.equals(type)) { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(boundBound); - return psiClass == null || !(((PsiWildcardType)bound).isExtends() && possibleClasses.contains(psiClass)); + if (psiClass == null) { + return true; + } + if (psiClass instanceof PsiTypeParameter) { + return try2ProveTypeParameterDistinct(type, psiClass); + } + return !(((PsiWildcardType)bound).isExtends() && possibleClasses.contains(psiClass)); } return false; } diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java index 8311ec0b199a..e4a4add097d0 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -41,10 +41,13 @@ import com.intellij.psi.impl.LanguageConstantExpressionEvaluator; import com.intellij.psi.impl.PsiExpressionEvaluator; import com.intellij.psi.impl.compiled.ClassFileStubBuilder; import com.intellij.psi.impl.file.PsiPackageImplementationHelper; +import com.intellij.psi.impl.search.MethodSuperSearcher; import com.intellij.psi.impl.source.tree.CoreJavaASTFactory; import com.intellij.psi.impl.source.tree.PlainTextASTFactory; import com.intellij.psi.presentation.java.*; +import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.stubs.BinaryFileStubBuilders; +import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.NotNull; /** @@ -98,6 +101,8 @@ public class JavaCoreApplicationEnvironment extends CoreApplicationEnvironment { } }); + registerApplicationExtensionPoint(SuperMethodsSearch.EP_NAME, QueryExecutor.class); + addExtension(SuperMethodsSearch.EP_NAME, new MethodSuperSearcher()); } @SuppressWarnings("MethodMayBeStatic") // overridden in upsource diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java index cc632cae8983..64169e127a6c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java @@ -852,6 +852,7 @@ public class ControlFlowUtil { private static PsiReferenceExpression findReferenceTo(PsiElement element, PsiVariable variable) { if (element instanceof PsiReferenceExpression + && !((PsiReferenceExpression)element).isQualified() && ((PsiReferenceExpression)element).resolve() == variable) { return (PsiReferenceExpression)element; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 67143a7b73a5..2a03a31bb3ea 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.*; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; @@ -711,6 +712,10 @@ public class PsiClassImplUtil { @Nullable public static PsiClassType correctType(PsiClassType originalType, final GlobalSearchScope resolveScope) { + if (!Registry.is("java.correct.class.type.by.place.resolve.scope")) { + return originalType; + } + final PsiClassType.ClassResolveResult originalResolveResult = originalType.resolveGenerics(); PsiClass superClass = originalResolveResult.getElement(); if (superClass == null) { @@ -746,7 +751,7 @@ public class PsiClassImplUtil { } }); if (substitute == null) return null; - + substitutor = substitutor.put(typeParameters[i], substitute); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java index 72256079a0fd..87df5dcb049d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java @@ -83,4 +83,14 @@ public class LightFieldBuilder extends LightVariableBuilder i public PsiClass getContainingClass() { return myContainingClass; } + + @Override + public boolean isEquivalentTo(PsiElement another) { + if (!(another instanceof PsiField)) return false; + if (!((PsiField)another).getName().equals(getName())) return false; + if (hasModifierProperty(PsiModifier.STATIC) != ((PsiField)another).hasModifierProperty(PsiModifier.STATIC)) return false; + final PsiClass containingClass = getContainingClass(); + final PsiClass anotherClass = ((PsiField)another).getContainingClass(); + return containingClass == null && anotherClass == null || getManager().areElementsEquivalent(containingClass, anotherClass); + } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java b/java/java-psi-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java similarity index 99% rename from java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java rename to java/java-psi-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java index acb5faae4947..d19b54fdd75c 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java index 23460fbda4fc..cf974c91f980 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java @@ -18,10 +18,12 @@ package com.intellij.psi.impl.source.resolve.graphInference.constraints; import com.intellij.codeInsight.ExceptionUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Condition; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable; import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; @@ -45,7 +47,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai } @Override - public boolean reduce(InferenceSession session, List constraints) { + public boolean reduce(final InferenceSession session, List constraints) { if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) { return true; } @@ -111,7 +113,12 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai } }); if (exceptions != null) { - thrownTypes.addAll(exceptions); + thrownTypes.addAll(ContainerUtil.filter(exceptions, new Condition() { + @Override + public boolean value(PsiClassType type) { + return session.isProperType(type) && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_EXCEPTION); + } + })); } } } else { @@ -169,7 +176,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai private static boolean isAddressed(List expectedThrownTypes, PsiType thrownType) { for (PsiType expectedThrownType : expectedThrownTypes) { - if (TypeConversionUtil.isAssignable(expectedThrownType, thrownType)) { + if (TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(thrownType), expectedThrownType)) { return true; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 2408bbba5bff..e640caf1f802 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -20,7 +20,6 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; @@ -480,7 +479,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase PsiClass qContainingClass = PsiMethodReferenceUtil.getQualifierResolveResult(this).getContainingClass(); if (qContainingClass != null && containingClass != null && - PsiMethodReferenceUtil.isReceiverType(left, containingClass, (PsiMethod)resolve)) { + PsiMethodReferenceUtil.isReceiverType(PsiMethodReferenceUtil.getFirstParameterType(left, this), qContainingClass, subst)) { subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); LOG.assertTrue(subst != null); } diff --git a/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_after.java b/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_after.java new file mode 100644 index 000000000000..edb36d680a69 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_after.java @@ -0,0 +1,14 @@ +import java.util.ArrayList; +import java.util.List; + + +public class Test { + + public static void main(String[] args) { + List list = new ArrayList(); + int a = 3; + +int b = 3; + } + +} diff --git a/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_before.java b/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_before.java new file mode 100644 index 000000000000..2256d473f765 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_before.java @@ -0,0 +1,17 @@ +import java.lang.String; +import java.util.List; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.HashSet; + + +public class Test { + + public static void main(String[] args) { +List list = new ArrayList(); +int a = 3; + +int b = 3; + } + +} diff --git a/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_after.java b/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_after.java new file mode 100644 index 000000000000..7e145c3004f0 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_after.java @@ -0,0 +1,11 @@ +public class Test { + + int a = 2; + int b = 3; + + + public void run() { + int myFirst = 12; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_before.java b/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_before.java new file mode 100644 index 000000000000..d753fc6562c6 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_before.java @@ -0,0 +1,11 @@ +public class Test { + + int a = 2; + int b = 3; + + + public void run() { + int myFirst = 12; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_after.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_after.java new file mode 100644 index 000000000000..b3c340724e6b --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_after.java @@ -0,0 +1,11 @@ +import java.util.ArrayList; +import java.util.List; + + +public class Test { + + public static void main(String[] args) { + List list = new ArrayList(); + } + +} diff --git a/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_before.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_before.java new file mode 100644 index 000000000000..a996d55202f7 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_before.java @@ -0,0 +1,14 @@ +import java.lang.String; +import java.util.List; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.HashSet; + + +public class Test { + + public static void main(String[] args) { +List list = new ArrayList(); + } + +} diff --git a/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_after.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_after.java new file mode 100644 index 000000000000..05460c51a74b --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_after.java @@ -0,0 +1,10 @@ +public class Test { + + public int a = 3; + + + public void test() { + int c = 3; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_before.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_before.java new file mode 100644 index 000000000000..e8d0ad4e5260 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_before.java @@ -0,0 +1,10 @@ +public class Test { + + public int a = 3; + + + public void test() { + int c = 3; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation.java b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation.java new file mode 100644 index 000000000000..4fd5cc0138d4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation.java @@ -0,0 +1,11 @@ +final class MyModule { + @Target({FIELD,PARAMETER,METHOD}) + @Retention(RUNTIME) + public static @interface Dependency { } +} + +final class SomeService { + + SomeService(@My) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation_after.java b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation_after.java new file mode 100644 index 000000000000..9ad5271d6b8d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation_after.java @@ -0,0 +1,11 @@ +final class MyModule { + @Target({FIELD,PARAMETER,METHOD}) + @Retention(RUNTIME) + public static @interface Dependency { } +} + +final class SomeService { + + SomeService(@MyModule.Dependency) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CastConversionToTypeParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CastConversionToTypeParameter.java new file mode 100644 index 000000000000..2499d4df03ef --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CastConversionToTypeParameter.java @@ -0,0 +1,7 @@ +import java.util.List; + +abstract class Test implements List { + private > T foo() { + return (T)this; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeDistinctProverForWildcardAndTypeParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeDistinctProverForWildcardAndTypeParameter.java new file mode 100644 index 000000000000..183eed87cf16 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeDistinctProverForWildcardAndTypeParameter.java @@ -0,0 +1,18 @@ +abstract class Test { + interface Selection {} + interface CriteriaQuery { + void select(Selection selection); + } + + private void foo(CriteriaQuery criteria, Selection array) { + criteria.select((Selection)array); + } + + private void foo1(CriteriaQuery criteria, Selection array) { + criteria.select((Selection)array); + } + + private void foo2(CriteriaQuery criteria, Selection array) { + criteria.select((Selection)array); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA134277.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA134277.java new file mode 100644 index 000000000000..e0956a029943 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA134277.java @@ -0,0 +1,18 @@ +import java.util.concurrent.Future; + +class TypeInferenceBug +{ + public interface Callback { + void done(V value); + } + + public static void addCallback(Future future, Callback callback) {} + + public static Callback createCallback() { + return value -> {}; + } + + public static void bind(Future future) { + addCallback(future, createCallback()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FieldInitializedUsedInLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FieldInitializedUsedInLambda.java new file mode 100644 index 000000000000..409670629123 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FieldInitializedUsedInLambda.java @@ -0,0 +1,17 @@ + +import java.util.Comparator; + +class Test { + private final int x; + + public Test(int x) { + this.x = x; + } + + public static final Comparator comparator = (o1, o2) -> { + if (o1.x == o2.x) { + } + this.x != o2.x; + return 0; + }; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java new file mode 100644 index 000000000000..476d30ab3cf2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java @@ -0,0 +1,38 @@ +import java.io.IOException; + +class Test { + + interface B { + K l(K k) throws E; + } + + void bar(B b) {} + + T baz(T l) throws E { + return null; + } + + { + bar(l -> baz(l)); + bar(this::baz); + } +} +class Test1 { + + interface B { + K l(K k) throws E; + } + + void bar(B b) {} + + class MyEx extends Exception{} + + T baz(T l) throws E { + return null; + } + + { + bar(l -> baz(l)); + bar(this::baz); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java new file mode 100644 index 000000000000..a0621c1726f7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java @@ -0,0 +1,28 @@ +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +class Test { + + static class Base { + public BigDecimal getTotal() { + return null; + } + } + + public static void foo(List list, List list1) { + System.out.println(add(list, Base::getTotal)); + list1.forEach(Base::getTotal); + } + + + public static BigDecimal add(Collection objectsThatHaveBigDecimals, Function functionToGet) { + return objectsThatHaveBigDecimals == null ? null : objectsThatHaveBigDecimals.stream().map(functionToGet).reduce(null, Test::add); + } + + public static BigDecimal add(BigDecimal... sequence) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136856.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136856.java new file mode 100644 index 000000000000..7b75b0feba20 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136856.java @@ -0,0 +1,43 @@ +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collector; + +class Test { + public static final Collector, Optional> toSingleton() { + return Collector.of( + AtomicReference::new, + (ref, v) -> { + if (!ref.compareAndSet(null, v) && v != null) { + throw new IllegalStateException("There is only one elvis."); + } + }, + (left, right) -> setOrFail(left, right.get()), + ref -> Optional.of(ref.get()) + ); + } + + public static final Collector, Optional> toSingleton1() { + return Collector.of( + AtomicReference::new, + (ref, v) -> setOrFail(ref, v), + (left, right) -> setOrFail(left, right.get()), + ref -> Optional.of(ref.get()) + ); + } + + public static final Collector, Optional> toSingleton2() { + return Collector.of( + AtomicReference::new, + Test::setOrFail, + (left, right) -> setOrFail(left, right.get()), + ref -> Optional.of(ref.get()) + ); + } + + private static final AtomicReference setOrFail(AtomicReference ref, T v) { + if (!ref.compareAndSet(null, v) && v != null) { + throw new IllegalStateException("There is only one elvis."); + } + return ref; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java new file mode 100644 index 000000000000..6015c09a1c24 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java @@ -0,0 +1,9 @@ +import java.util.Collection; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; + +class Test { + public static int sum(Collection collection, ToIntFunction mapper) { + return collection.stream().collect(Collectors.summingInt(mapper)); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/SecondConflictResolution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/SecondConflictResolution.java new file mode 100644 index 000000000000..ac48bcb9dc8b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/SecondConflictResolution.java @@ -0,0 +1,21 @@ + +import java.util.*; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.counting; +import static java.util.stream.Collectors.groupingBy; + +abstract class Token { + + + private static B getMode(Optional> max){ + return max + .flatMap(e -> Optional.of(new B<>(Long.valueOf(e.getValue().longValue())))) + .get(); + } + + static class B { + public B(K k) {} + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterMultipleImplementationsAlreadyExist.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterMultipleImplementationsAlreadyExist.java new file mode 100644 index 000000000000..c83805dbb2f9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterMultipleImplementationsAlreadyExist.java @@ -0,0 +1,20 @@ +// "Implement method 'foo'" "true" + +abstract class A { + abstract String foo(T t); +} + +class B extends A { + + @Override + String foo(String s1) { + return null; + } +} + +class ABC extends A { + @Override + String foo(Integer integer) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeMultipleImplementationsAlreadyExist.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeMultipleImplementationsAlreadyExist.java new file mode 100644 index 000000000000..eb475259b1e9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeMultipleImplementationsAlreadyExist.java @@ -0,0 +1,15 @@ +// "Implement method 'foo'" "true" + +abstract class A { + abstract String foo(T t); +} + +class B extends A { + + @Override + String foo(String s1) { + return null; + } +} + +class ABC extends A {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy index 89213c72649f..b27540c6a50d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy @@ -20,6 +20,9 @@ import com.intellij.codeInsight.generation.GenerateSetterHandler import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project +import com.intellij.psi.codeStyle.CodeStyleSettings +import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import com.intellij.psi.codeStyle.JavaCodeStyleManager import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.intellij.util.ui.UIUtil import com.siyeh.ig.style.UnqualifiedFieldAccessInspection @@ -70,6 +73,34 @@ class Foo { ''' } + public void "test strip field prefix"() { + def settings = CodeStyleSettingsManager.getInstance(getProject()).currentSettings + String oldPrefix = settings.FIELD_NAME_PREFIX + try { + settings.FIELD_NAME_PREFIX = "my" + myFixture.configureByText 'a.java', ''' + class Foo { + String myName; + + + } + ''' + generateGetter() + myFixture.checkResult ''' + class Foo { + String myName; + + public String getName() { + return myName; + } + } + ''' + } + finally { + settings.FIELD_NAME_PREFIX = oldPrefix + } + } + public void "test qualified this"() { myFixture.enableInspections(UnqualifiedFieldAccessInspection.class) myFixture.configureByText 'a.java', ''' @@ -91,6 +122,38 @@ class Foo { ''' } + public void "test nullable stuff"() { + myFixture.addClass("package org.jetbrains.annotations;\n" + + "public @interface NotNull {}") + myFixture.configureByText 'a.java', ''' +class Foo { + @org.jetbrains.annotations.NotNull + private String myName; + + +} +''' + generateGetter() + generateSetter() + myFixture.checkResult '''import org.jetbrains.annotations.NotNull; + +class Foo { + @org.jetbrains.annotations.NotNull + private String myName; + + public void setMyName(@NotNull String myName) { + this.myName = myName; + } + + @NotNull + public String getMyName() { + + return myName; + } +} +''' + } + private void generateGetter() { WriteCommandAction.runWriteCommandAction(getProject(), { new GenerateGetterHandler() { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy index 05a14ef267f0..b02d90b6d596 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy @@ -25,7 +25,7 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase */ class MultipleModuleHighlightingTest extends JavaCodeInsightFixtureTestCase { - @Bombed(day = 1, month = Calendar.MARCH) + @Bombed(day = 1, month = Calendar.APRIL) public void "test use original place classpath for reference type resolving"() { addTwoModules() @@ -60,7 +60,7 @@ class Class3 { myFixture.checkHighlighting() } - @Bombed(day = 1, month = Calendar.MARCH) + @Bombed(day = 1, month = Calendar.APRIL) public void "test use original place classpath for new expression type resolving"() { addTwoModules() diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java index 366fd626baaf..b780665d1c63 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java @@ -316,14 +316,9 @@ class AdditionalEventInfo { } } -class MockReformatFileSettings implements LayoutCodeOptions { - private boolean myProcessWholeFile; - private boolean myProcessDirectories; - private boolean myRearrange; - private boolean myIncludeSubdirs; +class MockReformatFileSettings implements ReformatFilesOptions { private boolean myOptimizeImports; - private boolean myProcessOnlyChangedText; - private boolean myIsOK = true; + private boolean myIncludeSubdirs; @Nullable @Override @@ -338,33 +333,13 @@ class MockReformatFileSettings implements LayoutCodeOptions { } @Override - public boolean isProcessWholeFile() { - return myProcessWholeFile; - } - - MockReformatFileSettings setProcessWholeFile(boolean processWholeFile) { - myProcessWholeFile = processWholeFile; - return this; + public TextRangeType getTextRangeType() { + return TextRangeType.WHOLE_FILE; } @Override - public boolean isProcessDirectory() { - return myProcessDirectories; - } - - MockReformatFileSettings setProcessDirectory(boolean processDirectories) { - myProcessDirectories = processDirectories; - return this; - } - - @Override - public boolean isRearrangeEntries() { - return myRearrange; - } - - @Override - public boolean isIncludeSubdirectories() { - return myIncludeSubdirs; + public boolean isRearrangeCode() { + return false; } @Override @@ -378,23 +353,6 @@ class MockReformatFileSettings implements LayoutCodeOptions { return this; } - @Override - public boolean isProcessOnlyChangedText() { - return myProcessOnlyChangedText; - } - - @NotNull - MockReformatFileSettings setProcessOnlyChangedText(boolean processOnlyChangedText) { - myProcessOnlyChangedText = processOnlyChangedText; - return this; - } - - @NotNull - MockReformatFileSettings setRearrange(boolean rearrange) { - myRearrange = rearrange; - return this; - } - @NotNull MockReformatFileSettings setIncludeSubdirs(boolean includeSubdirs) { myIncludeSubdirs = includeSubdirs; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java index 0dd2bcebc27d..058d165c3ddf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java @@ -16,106 +16,90 @@ package com.intellij.codeInsight.actions; import com.intellij.JavaTestUtil; -import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.psi.PsiFile; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; -public class ReformatCodeActionInEditorTest extends LightCodeInsightFixtureTestCase { +import static com.intellij.codeInsight.actions.TextRangeType.*; + +public class ReformatCodeActionInEditorTest extends LightPlatformCodeInsightFixtureTestCase { @Override protected String getTestDataPath() { return JavaTestUtil.getJavaTestDataPath() + "/actions/reformatFileInEditor/"; } - public void doTest(@NotNull ReformatFilesOptions options) { - setOptions(options); - - String before = null; - if (options.isProcessOnlyChangedText()) { - myFixture.configureByFile(getTestName(true) + "_revision.java"); - PsiFile file = myFixture.getFile(); - Document document = myFixture.getDocument(file); - before = document.getText(); - } - - myFixture.configureByFile(getTestName(true) + "_before.java"); - - if (before != null) { - myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, before); - } - - final String actionId = IdeActions.ACTION_EDITOR_REFORMAT; - AnAction action = ActionManager.getInstance().getAction(actionId); - - AnActionEvent event = createEventFor(action, getProject(), myFixture.getEditor()); - - action.actionPerformed(event); - myFixture.checkResultByFile(getTestName(true) + "_after.java"); - } - @Override public void tearDown() throws Exception { myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); super.tearDown(); } - protected AnActionEvent createEventFor(@NotNull AnAction action, @NotNull final Project project, @NotNull final Editor editor) { - return new AnActionEvent(null, new DataContext() { - @Nullable - @Override - public Object getData(@NonNls String dataId) { - if (CommonDataKeys.PROJECT.is(dataId)) return project; - if (CommonDataKeys.EDITOR.is(dataId)) return editor; - return null; - } - }, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0); + public void doTest(LayoutCodeOptions options) { + CharSequence revisionContent = null; + if (options.getTextRangeType() == VCS_CHANGED_TEXT) { + myFixture.configureByFile(getTestName(true) + "_revision.java"); + PsiFile file = myFixture.getFile(); + Document document = myFixture.getDocument(file); + revisionContent = document.getCharsSequence(); + } + + myFixture.configureByFile(getTestName(true) + "_before.java"); + if (revisionContent != null) { + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, revisionContent); + } + + FileInEditorProcessor processor = new FileInEditorProcessor(myFixture.getFile(), myFixture.getEditor(), options); + + processor.processCode(); + myFixture.checkResultByFile(getTestName(true) + "_after.java"); } - protected void setOptions(ReformatFilesOptions options) { - ReformatCodeAction.setTestOptions(options); + public void testSelectionReformat() { + doTest(new ReformatCodeRunOptions(SELECTED_TEXT)); + } + + public void testWholeFileReformat() { + doTest(new ReformatCodeRunOptions(WHOLE_FILE)); + } + + public void testWholeFileReformatAndOptimize() { + doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true)); + } + + public void testSelectedTextAndOptimizeImports() { + doTest(new ReformatCodeRunOptions(SELECTED_TEXT).setOptimizeImports(true)); } public void testFormatWholeFile() { - doTest(new MockReformatFileSettings().setProcessWholeFile(true)); + doTest(new ReformatCodeRunOptions(WHOLE_FILE)); } public void testFormatOptimizeWholeFile() { - doTest(new MockReformatFileSettings().setProcessWholeFile(true).setOptimizeImports(true)); + doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true)); } public void testFormatOptimizeRearrangeWholeFile() { - doTest(new MockReformatFileSettings().setProcessWholeFile(true).setOptimizeImports(true).setRearrange(true)); + doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true).setRearrangeCode(true)); } public void testFormatSelection() { - doTest(new MockReformatFileSettings().setProcessWholeFile(false)); + doTest(new ReformatCodeRunOptions(SELECTED_TEXT)); } public void testFormatRearrangeSelection() { - doTest(new MockReformatFileSettings().setProcessWholeFile(false).setRearrange(true)); + doTest(new ReformatCodeRunOptions(SELECTED_TEXT).setRearrangeCode(true)); } public void testFormatVcsChanges() { - doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true)); + doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT)); } public void testFormatOptimizeVcsChanges() { - doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true).setOptimizeImports(true)); + doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true)); } public void testFormatOptimizeRearrangeVcsChanges() { - doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true).setOptimizeImports(true).setRearrange(true)); + doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true).setRearrangeCode(true)); } - } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java index b0e4024ff076..09dff801a2f5 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java @@ -35,35 +35,10 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { public void testReformatAndOptimizeMultipleFiles() throws IOException { List files = createTestFiles(getTempRootDirectory(), classNames); injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); - performReformatActionOnSelectedFiles(files); checkFormationAndImportsOptimizationFor(files); } - public void testReformatSingleSelectedFile() throws IOException { - List files = createTestFiles(getTempRootDirectory(), classNames); - PsiFile fileToReformat = files.get(0); - List shouldNotBeFormatted = files.subList(1, files.size()); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); - - performReformatActionOnSelectedFile(fileToReformat); - - checkFormationAndImportsOptimizationFor(Arrays.asList(fileToReformat)); - checkNoProcessingWasPerformedOn(shouldNotBeFormatted); - } - - public void testReformatAndOptimizeFileFromEditor() throws IOException { - List files = createTestFiles(getTempRootDirectory(), classNames); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); - - PsiFile fileToFormat = files.get(0); - List shouldNotBeFormatted = files.subList(1, files.size()); - - performReformatActionOnFileInEditor(fileToFormat); - checkFormationAndImportsOptimizationFor(Arrays.asList(fileToFormat)); - checkNoProcessingWasPerformedOn(shouldNotBeFormatted); - } - public void testOptimizeAndReformatOnlySelectedFiles() throws IOException { List files = createTestFiles(getTempRootDirectory(), classNames); List forProcessing = ContainerUtil.newArrayList(files.get(0), files.get(1)); @@ -77,28 +52,6 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkNoProcessingWasPerformedOn(noProcessing); } - public void testOptimizeAndReformatAllFilesInDirectoryIncludeSubdirs() throws IOException { - TestFileStructure fileStructure = getThreeLevelDirectoryStructure(); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setProcessDirectory(true).setIncludeSubdirs(true)); - PsiFile fileInEditor = fileStructure.getFilesAtLevel(2).get(0); - List shouldNotBeFormatted = fileStructure.getFilesAtLevel(1); - - performReformatActionOnFileInEditor(fileInEditor); - - checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2), fileStructure.getFilesAtLevel(3)); - checkNoProcessingWasPerformedOn(shouldNotBeFormatted); - } - - public void testOptimizeAndReformatAllFilesInDirectoryExcludeSubdirs() throws IOException { - TestFileStructure fileStructure = getThreeLevelDirectoryStructure(); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setIncludeSubdirs(false)); - - performReformatActionOnSelectedFiles(fileStructure.getFilesAtLevel(2)); - - checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2)); - checkNoProcessingWasPerformedOn(fileStructure.getFilesAtLevel(1), fileStructure.getFilesAtLevel(3)); - } - public void testOptimizeAndReformatInModule() throws IOException { Module module = createModuleWithSourceRoot("newModule"); VirtualFile srcDir = ModuleRootManager.getInstance(module).getSourceRoots()[0]; @@ -109,26 +62,4 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkFormationAndImportsOptimizationFor(files); } - - private TestFileStructure getThreeLevelDirectoryStructure() throws IOException { - TestFileStructure fileStructure = new TestFileStructure(getModule(), getTempRootDirectory()); - - fileStructure.createDirectoryAndMakeItCurrent("dir"); - addFilesToCurrentDirectory(fileStructure); - - fileStructure.createDirectoryAndMakeItCurrent("innerDir"); - addFilesToCurrentDirectory(fileStructure); - - fileStructure.createDirectoryAndMakeItCurrent("innerInnerDir"); - addFilesToCurrentDirectory(fileStructure); - - return fileStructure; - } - - private void addFilesToCurrentDirectory(TestFileStructure fileStructure) throws IOException { - for (int i = 0; i < 5; i++) { - String className = "Test" + i; - fileStructure.addTestFile("Test" + i + ".java", getUntouchedJavaSourceForTotalProcessing(className)); - } - } } 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 d8abdbd5a9e8..0852028413bf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -932,6 +932,7 @@ public class ListUtils { public void testTabReplacesMethodNameWithLocalVariableName() throws Throwable { doTest('\t'); } public void testMethodParameterAnnotationClass() throws Throwable { doTest(); } + public void testInnerAnnotation() { doTest('\n'); } public void testPrimitiveCastOverwrite() throws Throwable { doTest '\t' } public void testClassReferenceInFor() throws Throwable { doTest ' ' } public void testClassReferenceInFor2() throws Throwable { doTest ' ' } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index ac8bb477b027..d61c5f0f096d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -455,6 +455,14 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testCastConversionToTypeParameter() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + + public void testTypeDistinctProverForWildcardAndTypeParameter() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); assertNotNull(collectionsClass); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java index 64b013d44df7..2630d5f999a6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java @@ -16,7 +16,6 @@ package com.intellij.codeInsight.daemon.lambda; import com.intellij.JavaTestUtil; -import com.intellij.idea.Bombed; import com.intellij.psi.*; import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.psi.search.searches.ReferencesSearch; @@ -25,7 +24,6 @@ import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; -import java.util.Calendar; import java.util.Collection; public class FindFunctionalInterfaceTest extends LightCodeInsightFixtureTestCase { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java index 4d04b70256b1..8e777ddaf0a7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java @@ -263,6 +263,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase doTest(); } + public void testIDEA134277() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java new file mode 100644 index 000000000000..e6934f2715e7 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2015 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.lambda; + +import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; +import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.testFramework.IdeaTestUtil; +import org.jetbrains.annotations.NonNls; + +public class Java8RegressionTest extends LightDaemonAnalyzerTestCase { + @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/regression"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + enableInspectionTool(new UnusedDeclarationInspection()); + } + + public void testIDEA136856() throws Exception { + doTest(); + } + + public void testIDEA136887() throws Exception { + doTest(); + } + + private void doTest() { + doTest(false); + } + + private void doTest(boolean warnings) { + IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable()); + doTest(BASE_PATH + "/" + getTestName(false) + ".java", warnings, false); + } + + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 868982e18bb8..673a5cfaa44a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -32,6 +32,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testStaticAccess() { doTest(); } public void testEffectiveFinal() { doTest(); } + public void testFieldInitializedUsedInLambda() {doTest();} public void testReassignUsedVars() { doTest(); } public void testLambdaContext() { doTest(); } public void testReturnTypeCompatibility() { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index d53205a820cb..f0636eb92e57 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -80,7 +80,6 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testLiftedIntersectionType() { doTest(); } public void testInferenceFromReturnStatements() { doTest(); } public void testDownUpThroughLambdaReturnStatements() { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testIDEA124547() { doTest(); } public void testIDEA118362() { doTest(); } public void testIDEA126056() { doTest(); } @@ -139,11 +138,14 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testCheckedExceptionsConstraintsSubstitutions() throws Exception { doTest(); } + public void testCheckedExceptionsConstraintsSubstitutions1() throws Exception { + doTest(); + } + public void testCheckedExceptionsConstraintsSubstitutionsDeepInBody() throws Exception { doTest(); } @@ -168,7 +170,6 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testIDEA127124() throws Exception { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 60ad003549b3..dad206251e3e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -19,15 +19,12 @@ import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; -import com.intellij.idea.Bombed; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.testFramework.IdeaTestUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import java.util.Calendar; - public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef"; @@ -373,7 +370,6 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testIDEA132379() throws Exception { doTest(); } @@ -386,6 +382,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(false); } + public void testSecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java index 8a9a451c14da..5d8cd07c3270 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java @@ -21,6 +21,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.ResolveTestCase; @@ -30,6 +31,14 @@ public class TypeInference18Test extends ResolveTestCase { doTest(); } + public void testSecondConflictResolution() throws Exception { + PsiReference ref = configureByFile("/codeInsight/daemonCodeAnalyzer/lambda/resolve/" + getTestName(false) + ".java"); + assertNotNull(ref); + PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(ref.getElement(), PsiMethodCallExpression.class); + assertNotNull(methodCallExpression); + assertNotNull(methodCallExpression.resolveMethod()); + } + private LanguageLevel myOldLanguageLevel; @Override diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java index 8bf2fb1d4284..384fdc3eb339 100644 --- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java @@ -365,6 +365,19 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { assertSize(1, findUsages(findModel)); } + public void testNonSourceContent() throws Exception { + VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(createTempDirectory()); + PsiTestUtil.addContentRoot(myModule, root); + + createFile(myModule, root, "A.txt", "goo doo"); + + FindModel findModel = FindManagerTestUtils.configureFindModel("goo"); + findModel.setProjectScope(false); + findModel.setModuleName(myModule.getName()); + + assertSize(1, findUsages(findModel)); + } + public void testReplaceRegexp() { FindModel findModel = new FindModel(); findModel.setStringToFind("bug_(?=here)"); @@ -537,6 +550,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { findModel.setFromCursor(false); findModel.setGlobal(true); findModel.setMultipleFiles(true); + findModel.setCustomScope(true); ThrowableRunnable test = new ThrowableRunnable() { @Override @@ -573,6 +587,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { VirtualFile file = tempDirFixture.createFile("a.txt", "foo bar foo"); FindModel findModel = FindManagerTestUtils.configureFindModel("foo"); findModel.setWholeWordsOnly(true); + findModel.setCustomScope(true); findModel.setCustomScope(new LocalSearchScope(PsiManager.getInstance(myProject).findFile(file))); assertSize(2, findUsages(findModel)); } diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index 93e35b20b965..9b7c1c6cdf29 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -446,7 +446,8 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { ParameterInfo nameInfo = builder.findParameterization(name); ParameterInfo typeInfo = builder.findParameterization(type); - if (nameInfo != null && typeInfo != null && !(parameter.getParent() instanceof PsiCatchSection)) { + final PsiElement scope = parameter.getDeclarationScope(); + if (nameInfo != null && typeInfo != null && !(scope instanceof PsiCatchSection) && !(scope instanceof PsiForeachStatement)) { nameInfo.setArgumentContext(false); typeInfo.setArgumentContext(false); typeInfo.setMethodParameterContext(true); diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index c8dca645f698..467b18f1778c 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -1205,9 +1205,10 @@ public class JavaMatchingVisitor extends JavaElementVisitor { public void visitIfStatement(final PsiIfStatement if1) { final PsiIfStatement if2 = (PsiIfStatement)myMatchingVisitor.getElement(); + final PsiStatement elseBranch = if1.getElseBranch(); myMatchingVisitor.setResult(myMatchingVisitor.match(if1.getCondition(), if2.getCondition()) && compareBody(if1.getThenBranch(), if2.getThenBranch()) && - compareBody(if1.getElseBranch(), if2.getElseBranch())); + (elseBranch == null || compareBody(elseBranch, if2.getElseBranch()))); } @Override diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java index 84627a339de8..afb1f271a597 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java @@ -84,7 +84,7 @@ public class CompileScopeImpl extends CompileScope { @Override public boolean isAffected(BuildTarget target, @NotNull File file) { if (myFiles.isEmpty()) {//optimization - return true; + return isAffected(target); } final Set files = myFiles.get(target); return files != null && files.contains(file); diff --git a/lib/markdown4j-2.2.jar b/lib/markdown4j-2.2.jar new file mode 100644 index 000000000000..65030fa08205 Binary files /dev/null and b/lib/markdown4j-2.2.jar differ diff --git a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java index 738e970fbca1..2de6b80ee9f4 100644 --- a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java +++ b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java @@ -60,7 +60,7 @@ public class HighlightDisplayLevel { */ @Deprecated public static final HighlightDisplayLevel INFO = new HighlightDisplayLevel(HighlightSeverity.INFO, DO_NOT_SHOW.getIcon()); - public static final HighlightDisplayLevel WEAK_WARNING = new HighlightDisplayLevel(HighlightSeverity.WEAK_WARNING, DO_NOT_SHOW.getIcon()); + public static final HighlightDisplayLevel WEAK_WARNING = new HighlightDisplayLevel(HighlightSeverity.WEAK_WARNING, createIconByKey(CodeInsightColors.WEAK_WARNING_ATTRIBUTES)); public static final HighlightDisplayLevel NON_SWITCHABLE_ERROR = new HighlightDisplayLevel(HighlightSeverity.ERROR); diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java index 00fa3f0f4cff..9fc611d6dbbc 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.codeInsight.daemon; import com.intellij.openapi.components.ServiceManager; +import com.intellij.util.xmlb.annotations.OptionTag; import com.intellij.util.xmlb.annotations.Transient; public class DaemonCodeAnalyzerSettings { @@ -26,9 +26,9 @@ public class DaemonCodeAnalyzerSettings { public boolean NEXT_ERROR_ACTION_GOES_TO_ERRORS_FIRST = true; public int AUTOREPARSE_DELAY = 300; - public boolean SHOW_ADD_IMPORT_HINTS = true; + protected boolean myShowAddImportHints = true; public String NO_AUTO_IMPORT_PATTERN = "[a-z].?"; - public boolean SUPPRESS_WARNINGS = true; + protected boolean mySuppressWarnings = true; public boolean SHOW_METHOD_SEPARATORS = false; public int ERROR_STRIPE_MARK_MIN_HEIGHT = 2; public boolean SHOW_SMALL_ICONS_IN_GUTTER = true; @@ -38,21 +38,21 @@ public class DaemonCodeAnalyzerSettings { return false; } - @Transient + @OptionTag(value = "SHOW_ADD_IMPORT_HINTS") public boolean isImportHintEnabled() { - return SHOW_ADD_IMPORT_HINTS; + return myShowAddImportHints; } public void setImportHintEnabled(boolean isImportHintEnabled) { - SHOW_ADD_IMPORT_HINTS = isImportHintEnabled; + myShowAddImportHints = isImportHintEnabled; } - @Transient + @OptionTag(value = "SUPPRESS_WARNINGS") public boolean isSuppressWarnings() { - return SUPPRESS_WARNINGS; + return mySuppressWarnings; } public void setSuppressWarnings(boolean suppressWarnings) { - SUPPRESS_WARNINGS = suppressWarnings; + mySuppressWarnings = suppressWarnings; } } diff --git a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java index 29a8905a45b9..6e313990e112 100644 --- a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java +++ b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java @@ -20,7 +20,6 @@ import com.intellij.idea.Main; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.lang.UrlClassLoader; import com.intellij.util.text.StringTokenizer; @@ -28,13 +27,10 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import java.util.*; import java.util.regex.Pattern; /** @@ -55,14 +51,14 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { public static ClassLoader initClassLoader(boolean updatePlugins) throws MalformedURLException { PathManager.loadProperties(); - List classpath = new ArrayList(); + Collection classpath = new LinkedHashSet(); addParentClasspath(classpath); addIDEALibraries(classpath); addAdditionalClassPath(classpath); UrlClassLoader.Builder builder = UrlClassLoader.build() - .urls(filterClassPath(classpath)) - .allowLock() + .urls(filterClassPath(new ArrayList(classpath))) + .allowLock(false) .usePersistentClasspathIndexForLocalClassDirectories() .useCache(); if (Boolean.valueOf(System.getProperty(PROPERTY_ALLOW_BOOTSTRAP_RESOURCES, "true"))) { @@ -85,68 +81,35 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { return newClassLoader; } - private static List filterClassPath(List classpathElements) { - String ignoreProperty = System.getProperty(PROPERTY_IGNORE_CLASSPATH); - if (ignoreProperty != null) { - Pattern pattern = Pattern.compile(ignoreProperty); - for (Iterator i = classpathElements.iterator(); i.hasNext(); ) { - String url = i.next().toExternalForm(); - if (pattern.matcher(url).matches()) { - i.remove(); - } - } - } - return classpathElements; - } - - private static void addParentClasspath(List classpathElements) throws MalformedURLException { + private static void addParentClasspath(Collection classpath) throws MalformedURLException { + List loaders = new ArrayList(2); for (ClassLoader loader = BootstrapClassLoaderUtil.class.getClassLoader(); loader != null; loader = loader.getParent()) { if (loader instanceof URLClassLoader) { - ContainerUtil.addAll(classpathElements, ((URLClassLoader)loader).getURLs()); + loaders.add(0, (URLClassLoader)loader); } else { - String loaderName = loader.getClass().getName(); - try { - Class antClassLoaderClass = Class.forName("org.apache.tools.ant.AntClassLoader"); - if (antClassLoaderClass.isInstance(loader) || - "org.apache.tools.ant.AntClassLoader".equals(loaderName) || - "org.apache.tools.ant.loader.AntClassLoader2".equals(loaderName)) { - String classpath = (String)antClassLoaderClass - .getDeclaredMethod("getClasspath", ArrayUtil.EMPTY_CLASS_ARRAY) - .invoke(loader, ArrayUtil.EMPTY_OBJECT_ARRAY); - StringTokenizer tokenizer = new StringTokenizer(classpath, File.separator, false); - while (tokenizer.hasMoreTokens()) { - String token = tokenizer.nextToken(); - classpathElements.add(new File(token).toURI().toURL()); - } - } - else { - getLogger().warn("Unknown class loader: " + loaderName); - } - } - catch (ClassCastException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (ClassNotFoundException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (NoSuchMethodException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (IllegalAccessException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (InvocationTargetException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } + getLogger().warn("Unknown class loader: " + loader.getClass().getName()); } } + for (URLClassLoader loader : loaders) { + ContainerUtil.addAll(classpath, loader.getURLs()); + } } - private static void addIDEALibraries(List classpathElements) throws MalformedURLException { + private static void addIDEALibraries(Collection classpath) throws MalformedURLException { Class aClass = BootstrapClassLoaderUtil.class; String selfRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class"); assert selfRoot != null; URL selfRootUrl = new File(selfRoot).getAbsoluteFile().toURI().toURL(); - classpathElements.add(selfRootUrl); + classpath.add(selfRootUrl); File libFolder = new File(PathManager.getLibPath()); - addLibraries(classpathElements, libFolder, selfRootUrl); - addLibraries(classpathElements, new File(libFolder, "ext"), selfRootUrl); - addLibraries(classpathElements, new File(libFolder, "ant/lib"), selfRootUrl); + addLibraries(classpath, libFolder, selfRootUrl); + addLibraries(classpath, new File(libFolder, "ext"), selfRootUrl); + addLibraries(classpath, new File(libFolder, "ant/lib"), selfRootUrl); } - private static void addLibraries(List classPath, File fromDir, URL selfRootUrl) throws MalformedURLException { + private static void addLibraries(Collection classPath, File fromDir, URL selfRootUrl) throws MalformedURLException { File[] files = fromDir.listFiles(); if (files == null) return; @@ -160,16 +123,30 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { } } - private static void addAdditionalClassPath(List classPath) { + private static void addAdditionalClassPath(Collection classpath) { try { StringTokenizer tokenizer = new StringTokenizer(System.getProperty(PROPERTY_ADDITIONAL_CLASSPATH, ""), File.pathSeparator, false); while (tokenizer.hasMoreTokens()) { String pathItem = tokenizer.nextToken(); - classPath.add(new File(pathItem).toURI().toURL()); + classpath.add(new File(pathItem).toURI().toURL()); } } catch (MalformedURLException e) { getLogger().error(e); } } + + private static List filterClassPath(List classpath) { + String ignoreProperty = System.getProperty(PROPERTY_IGNORE_CLASSPATH); + if (ignoreProperty != null) { + Pattern pattern = Pattern.compile(ignoreProperty); + for (Iterator i = classpath.iterator(); i.hasNext(); ) { + String url = i.next().toExternalForm(); + if (pattern.matcher(url).matches()) { + i.remove(); + } + } + } + return classpath; + } } diff --git a/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java b/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java index c9d4bd59ec59..bd98d77dd987 100644 --- a/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java +++ b/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java @@ -17,8 +17,6 @@ package com.intellij.openapi.editor.markup; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.JDOMExternalizable; -import com.intellij.openapi.util.WriteExternalException; import org.intellij.lang.annotations.JdkConstants; import org.jdom.Element; import org.jetbrains.annotations.Contract; @@ -30,7 +28,7 @@ import java.awt.*; /** * Defines the visual representation (colors and effects) of text. */ -public class TextAttributes implements JDOMExternalizable, Cloneable { +public class TextAttributes implements Cloneable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.markup.TextAttributes"); public static final TextAttributes ERASE_MARKER = new TextAttributes(); @@ -77,7 +75,7 @@ public class TextAttributes implements JDOMExternalizable, Cloneable { myEnforcedDefaults = enforced; } - public TextAttributes(@NotNull Element element) throws InvalidDataException { + public TextAttributes(@NotNull Element element) { readExternal(element); } @@ -191,14 +189,20 @@ public class TextAttributes implements JDOMExternalizable, Cloneable { return myAttrs.hashCode(); } - @Override - public void readExternal(Element element) throws InvalidDataException { - myAttrs = AttributesFlyweight.create(element); - if (isEmpty()) myEnforcedDefaults = true; + public void readExternal(Element element) { + try { + myAttrs = AttributesFlyweight.create(element); + } + catch (InvalidDataException e) { + throw new RuntimeException(e); + } + + if (isEmpty()) { + myEnforcedDefaults = true; + } } - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void writeExternal(Element element) { myAttrs.writeExternal(element); } diff --git a/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java b/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java index 845e50fbe804..e9630d633000 100644 --- a/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java +++ b/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java @@ -27,7 +27,7 @@ import java.io.IOException; /** * @author yole */ -public abstract class BaseSchemeProcessor implements SchemeProcessor { +public abstract class BaseSchemeProcessor implements SchemeProcessor, SchemeExtensionProvider { @Override public void initScheme(@NotNull T scheme) { } @@ -75,4 +75,15 @@ public abstract class BaseSchemeProcessor implem public State getState(@NotNull T scheme) { return shouldBeSaved(scheme) ? State.POSSIBLY_CHANGED : State.NON_PERSISTENT; } + + @Override + public boolean isUpgradeNeeded() { + return false; + } + + @NotNull + @Override + public String getSchemeExtension() { + return ".xml"; + } } diff --git a/platform/platform-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java b/platform/core-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java similarity index 100% rename from platform/platform-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java rename to platform/core-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java diff --git a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java index cef94aefcc06..c085400d9465 100644 --- a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java +++ b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java @@ -15,94 +15,43 @@ */ package com.intellij.openapi.options; +import com.intellij.util.ThrowableConvertor; +import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.Collection; -import java.util.Collections; import java.util.List; -public interface SchemesManager { - SchemesManager EMPTY = new SchemesManager(){ - @Override - @NotNull - public Collection loadSchemes() { - return Collections.emptySet(); - } +public abstract class SchemesManager { + @NotNull + public abstract Collection loadSchemes(); - @Override - public void addNewScheme(@NotNull final Scheme scheme, final boolean replaceExisting) { - } + public abstract void addNewScheme(@NotNull T scheme, final boolean replaceExisting); - @Override - public void clearAllSchemes() { - } - - @Override - @NotNull - public List getAllSchemes() { - return Collections.emptyList(); - } - - @Override - public Scheme findSchemeByName(@NotNull String schemeName) { - return null; - } - - @Override - public void save() { - } - - @Override - public void setCurrentSchemeName(String schemeName) { - } - - @Override - public Scheme getCurrentScheme() { - return null; - } - - @Override - public void removeScheme(@NotNull Scheme scheme) { - } - - @Override - @NotNull - public Collection getAllSchemeNames() { - return Collections.emptySet(); - } - - @Override - public File getRootDirectory() { - return null; - } - }; + public abstract void clearAllSchemes(); @NotNull - Collection loadSchemes(); - - void addNewScheme(@NotNull T scheme, final boolean replaceExisting); - - void clearAllSchemes(); - - @NotNull - List getAllSchemes(); + public abstract List getAllSchemes(); @Nullable - T findSchemeByName(@NotNull String schemeName); + public abstract T findSchemeByName(@NotNull String schemeName); - void save(); + public abstract void save(); - void setCurrentSchemeName(@Nullable String schemeName); + public abstract void setCurrentSchemeName(@Nullable String schemeName); @Nullable - T getCurrentScheme(); + public abstract T getCurrentScheme(); - void removeScheme(@NotNull T scheme); + public abstract void removeScheme(@NotNull T scheme); @NotNull - Collection getAllSchemeNames(); + public abstract Collection getAllSchemeNames(); - File getRootDirectory(); + public abstract File getRootDirectory(); + + public void loadBundledScheme(@NotNull String resourceName, @NotNull Object requestor, @NotNull ThrowableConvertor convertor) { + } } diff --git a/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java b/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java deleted file mode 100644 index a0f59d39f521..000000000000 --- a/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2013 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.options; - -import org.jetbrains.annotations.NotNull; - -@Deprecated -public class SharedScheme { - private final String myUserName; - private final String myDescription; - private final E myScheme; - - public SharedScheme(@NotNull String userName, final String description, @NotNull E scheme) { - myUserName = userName; - myDescription = description; - myScheme = scheme; - } - - @NotNull - public String getUserName() { - return myUserName; - } - - public String getDescription() { - return myDescription; - } - - @NotNull - public E getScheme() { - return myScheme; - } -} diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbService.java b/platform/core-api/src/com/intellij/openapi/project/DumbService.java index 68ca99133e46..efd18fbf8805 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbService.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbService.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.NotNullLazyKey; import com.intellij.openapi.util.Ref; import com.intellij.util.messages.Topic; @@ -37,9 +38,6 @@ import java.util.List; * A service managing IDEA's 'dumb' mode: when indices are updated in background and the functionality is very much limited. * Only the explicitly allowed functionality is available. Usually it's allowed by implementing {@link DumbAware} interface. * - * If you want to register a toolwindow, which will be enabled during the dumb mode, please use {@link com.intellij.openapi.wm.ToolWindowManager}'s - * registration methods which have 'canWorkInDumMode' parameter. - * * @author peter */ public abstract class DumbService { @@ -50,6 +48,11 @@ public abstract class DumbService { */ public static final Topic DUMB_MODE = new Topic("dumb mode", DumbModeListener.class); + /** + * The tracker is advanced each time we enter/exit from dumb mode. + */ + public abstract ModificationTracker getModificationTracker(); + /** * @return whether IntelliJ IDEA is in dumb mode, which means that right now indices are updated in background. * IDEA offers only limited functionality at such times, e.g. plain text file editing and version control operations. diff --git a/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java b/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java new file mode 100644 index 000000000000..b8bd9641ab31 --- /dev/null +++ b/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2013 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.project; + +import com.intellij.openapi.util.Computable; + +/** + * Thrown on accessing indices when they're not ready, in so-called dumb mode. Possible fixes: + *
    + *
  • If {@link com.intellij.openapi.actionSystem.AnAction#actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent)} is in stack trace, + * consider making the action not implement {@link DumbAware}. + * + *
  • A {@link DumbAware} action, having got this exception, may just notify the user that the requested activity is not possible while + * indexing is in progress. It can be done via a dialog (see {@link com.intellij.openapi.ui.Messages}) or a status bar balloon + * (see {@link DumbService#showDumbModeNotification(String)}, {@link com.intellij.openapi.actionSystem.ex.ActionUtil#showDumbModeWarning(com.intellij.openapi.actionSystem.AnActionEvent...)}). + * + *
  • If index access is performed from some non-urgent invokeLater activity, consider replacing it with + * {@link DumbService#smartInvokeLater(Runnable)}. Note that this 'later' can be very late, several minutes may pass. So if that code + * involves user interaction, {@link DumbService#smartInvokeLater(Runnable)} should probably not be used to avoid dialogs popping out of the blue. + * + *
  • If it's a non-urgent background process (e.g. compilation, usage search), consider replacing topmost read-action with + * {@link DumbService#runReadActionInSmartMode(Computable)}. + * + *
  • If the exception comes from within Java's findClass call, and the IDE is currently performing a user-initiated action or a + * task when skipping findClass would lead to very negative consequences (e.g. not stopping at a breakpoint), then it might be possible + * to avoid index query by using alternative resolve (and findClass) strategy, which is significantly slower and might return null. To do this, + * use {@link DumbService#setAlternativeResolveEnabled(boolean)}. + * + *
  • It's preferable to avoid the exception entirely by adding {@link DumbService#isDumb()} checks where necessary. + *
+ * + * @author peter + * @see DumbService + * @see DumbAware + */ +public class IndexNotReadyException extends RuntimeException { + + @Override + public String getMessage() { + return "Please change caller according to " + IndexNotReadyException.class.getName() + " documentation"; + } +} diff --git a/platform/core-impl/src/com/intellij/mock/MockDumbService.java b/platform/core-impl/src/com/intellij/mock/MockDumbService.java index b1fe7ae2a727..e97a9f64c7f3 100644 --- a/platform/core-impl/src/com/intellij/mock/MockDumbService.java +++ b/platform/core-impl/src/com/intellij/mock/MockDumbService.java @@ -22,6 +22,8 @@ import com.intellij.openapi.project.DumbModeTask; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.ModificationTracker; +import com.intellij.openapi.util.SimpleModificationTracker; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -36,6 +38,11 @@ public class MockDumbService extends DumbService { myProject = project; } + @Override + public ModificationTracker getModificationTracker() { + return new SimpleModificationTracker(); + } + @Override public boolean isDumb() { return false; diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 5543c430f361..a7f54fc9c8dd 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -770,10 +770,10 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { } private void assertInsideCommand() { + if (!myAssertThreading) return; CommandProcessor commandProcessor = CommandProcessor.getInstance(); if (!commandProcessor.isUndoTransparentActionInProgress() && - commandProcessor.getCurrentCommand() == null && - myAssertThreading) { + commandProcessor.getCurrentCommand() == null) { throw new IncorrectOperationException("Must not change document outside command or undo-transparent action. See com.intellij.openapi.command.WriteCommandAction or com.intellij.openapi.command.CommandProcessor"); } } diff --git a/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java b/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java index d4f3f707d4e6..14f3b057a5fc 100644 --- a/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java +++ b/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -public abstract class AbstractSchemesManager implements SchemesManager { +public abstract class AbstractSchemesManager extends SchemesManager { private static final Logger LOG = Logger.getInstance(AbstractSchemesManager.class); protected final List mySchemes = new ArrayList(); diff --git a/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java b/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java new file mode 100644 index 000000000000..55a74d08ebd1 --- /dev/null +++ b/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2015 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.options; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class EmptySchemesManager extends SchemesManager { + @Override + @NotNull + public Collection loadSchemes() { + return Collections.emptySet(); + } + + @Override + public void addNewScheme(@NotNull final Scheme scheme, final boolean replaceExisting) { + } + + @Override + public void clearAllSchemes() { + } + + @Override + @NotNull + public List getAllSchemes() { + return Collections.emptyList(); + } + + @Override + public Scheme findSchemeByName(@NotNull String schemeName) { + return null; + } + + @Override + public void save() { + } + + @Override + public void setCurrentSchemeName(String schemeName) { + } + + @Override + public Scheme getCurrentScheme() { + return null; + } + + @Override + public void removeScheme(@NotNull Scheme scheme) { + } + + @Override + @NotNull + public Collection getAllSchemeNames() { + return Collections.emptySet(); + } + + @Override + public File getRootDirectory() { + return null; + } +} diff --git a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java index b71a7e5e4f78..816ea9595797 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java @@ -26,7 +26,6 @@ import com.intellij.diff.tools.external.ExternalDiffTool; import com.intellij.diff.tools.fragmented.OnesideDiffTool; import com.intellij.diff.tools.simple.SimpleDiffTool; import com.intellij.openapi.Disposable; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import org.jetbrains.annotations.NotNull; @@ -34,11 +33,10 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class DiffManagerImpl extends DiffManagerEx { - private static final Logger LOG = Logger.getInstance(DiffManagerImpl.class); - @Override public void showDiff(@Nullable Project project, @NotNull DiffRequest request) { showDiff(project, request, DiffDialogHints.DEFAULT); @@ -88,16 +86,11 @@ public class DiffManagerImpl extends DiffManagerEx { @Override public List getDiffTools() { List result = new ArrayList(); - result.add(SimpleDiffTool.INSTANCE); result.add(OnesideDiffTool.INSTANCE); result.add(BinaryDiffTool.INSTANCE); result.add(DirDiffTool.INSTANCE); - - for (DiffTool tool : DiffTool.EP_NAME.getExtensions()) { - result.add(tool); - } - + Collections.addAll(result, DiffTool.EP_NAME.getExtensions()); return result; } } diff --git a/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java b/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java index 2e321952643a..4e00df7f1e41 100644 --- a/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java +++ b/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java @@ -42,8 +42,31 @@ public class CompareFilesAction extends BaseShowDiffAction { VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY); - String text = getTemplatePresentation().getText(); - if (files != null && files.length == 1) text += "..."; + String text = "Compare Files"; + if (files != null && files.length == 1) { + text = "Compare With..."; + } + else if (files != null && files.length == 2) { + Type type1 = getType(files[0]); + Type type2 = getType(files[1]); + + if (type1 != type2) { + text = "Compare"; + } + else { + switch (type1) { + case FILE: + text = "Compare Files"; + break; + case DIRECTORY: + text = "Compare Directories"; + break; + case ARCHIEVE: + text = "Compare Archieves"; + break; + } + } + } e.getPresentation().setText(text); } @@ -93,7 +116,9 @@ public class CompareFilesAction extends BaseShowDiffAction { private static VirtualFile getOtherFile(@Nullable Project project, @NotNull VirtualFile file) { FileChooserDescriptor descriptor; String key; - if (file.isDirectory() || file.getFileType() instanceof ArchiveFileType) { + + Type type = getType(file); + if (type == Type.DIRECTORY || type == Type.ARCHIEVE) { descriptor = new FileChooserDescriptor(false, true, true, false, false, false); key = LAST_USED_FOLDER_KEY; } @@ -121,4 +146,14 @@ public class CompareFilesAction extends BaseShowDiffAction { if (project == null) return; PropertiesComponent.getInstance(project).setValue(key, file.getPath()); } + + @NotNull + private static Type getType(@Nullable VirtualFile file) { + if (file == null) return Type.FILE; + if (file.isDirectory()) return Type.DIRECTORY; + if (file.getFileType() instanceof ArchiveFileType) return Type.ARCHIEVE; + return Type.FILE; + } + + private enum Type {FILE, DIRECTORY, ARCHIEVE} } diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java index 5da3e9afc46f..a8d07656c78c 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java @@ -15,6 +15,9 @@ */ package com.intellij.diff.impl; +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.hint.HintManagerImpl; +import com.intellij.codeInsight.hint.HintUtil; import com.intellij.diff.DiffContext; import com.intellij.diff.DiffManagerEx; import com.intellij.diff.DiffTool; @@ -37,15 +40,20 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.util.*; import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy; +import com.intellij.ui.HintHint; +import com.intellij.ui.LightweightHint; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NonNls; @@ -624,7 +632,7 @@ public abstract class DiffRequestProcessor implements Disposable { if (myIterationState != IterationState.NEXT) { // TODO: provide "change" word in chain UserData - for tests/etc - if (iterable != null) iterable.notify("Press again to go to the next file"); + notifyMessage(e.getData(DiffDataKeys.CURRENT_EDITOR), "Press again to go to the next file", true); myIterationState = IterationState.NEXT; return; } @@ -667,7 +675,7 @@ public abstract class DiffRequestProcessor implements Disposable { if (!isNavigationEnabled() || !hasPrevChange()) return; if (myIterationState != IterationState.PREV) { - if (iterable != null) iterable.notify("Press again to go to the previous file"); + notifyMessage(e.getData(DiffDataKeys.CURRENT_EDITOR), "Press again to go to the previous file", false); myIterationState = IterationState.PREV; return; } @@ -676,6 +684,29 @@ public abstract class DiffRequestProcessor implements Disposable { } } + private void notifyMessage(@Nullable Editor editor, @NotNull String message, boolean next) { + final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); + Point point = new Point(myContentPanel.getWidth() / 2, next ? myContentPanel.getHeight() - JBUI.scale(40) : JBUI.scale(40)); + + final HintHint hintHint = new HintHint(myContentPanel, point) + .setPreferredPosition(next ? Balloon.Position.above : Balloon.Position.below) + .setAwtTooltip(true) + .setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD)) + .setTextBg(HintUtil.INFORMATION_COLOR) + .setShowImmediately(true); + + if (editor == null) { + final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + hint.show(myContentPanel, point.x, point.y, owner instanceof JComponent ? (JComponent)owner : null, hintHint); + } + else { + Point editorPoint = SwingUtilities.convertPoint(myContentPanel, point, editor.getComponent()); + HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, editorPoint, HintManager.HIDE_BY_ANY_KEY | + HintManager.HIDE_BY_TEXT_CHANGE | + HintManager.HIDE_BY_SCROLLING, 0, false, hintHint); + } + } + // Iterate requests protected class MyNextChangeAction extends NextChangeAction { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java index dd0a87dd7dfc..dc0b4fae73ea 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java @@ -44,7 +44,7 @@ public class ErrorDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Error Viewer"; + return "Error viewer"; } private static class MyViewer implements DiffViewer { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java index 542ce0779bc4..a3fe98a865a4 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java @@ -37,6 +37,6 @@ public class BinaryDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Binary File Viewer"; + return "Binary file viewer"; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java index 98786884cb1d..b362604c5f96 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java @@ -23,17 +23,21 @@ import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.contents.FileContent; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; +import com.intellij.ide.DataManager; import com.intellij.ide.diff.DiffElement; import com.intellij.ide.diff.DirDiffSettings; import com.intellij.ide.diff.JarFileDiffElement; import com.intellij.ide.diff.VirtualFileDiffElement; import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.diff.impl.dir.DirDiffFrame; import com.intellij.openapi.diff.impl.dir.DirDiffPanel; import com.intellij.openapi.diff.impl.dir.DirDiffTableModel; import com.intellij.openapi.diff.impl.dir.DirDiffWindow; import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,7 +50,8 @@ class DifDiffViewer implements FrameDiffTool.DiffViewer { @NotNull private final DiffContext myContext; @NotNull private final ContentDiffRequest myRequest; - @NotNull private final DirDiffPanel myPanel; + @NotNull private final DirDiffPanel myDirDiffPanel; + @NotNull private final JPanel myPanel; public DifDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request) { myContext = context; @@ -57,7 +62,7 @@ class DifDiffViewer implements FrameDiffTool.DiffViewer { DiffElement element2 = createDiffElement(contents.get(1)); DirDiffTableModel model = new DirDiffTableModel(context.getProject(), element1, element2, new DirDiffSettings()); - myPanel = new DirDiffPanel(model, new DirDiffWindow((DirDiffFrame)null) { + myDirDiffPanel = new DirDiffPanel(model, new DirDiffWindow((DirDiffFrame)null) { @Override public Window getWindow() { return null; @@ -72,31 +77,43 @@ class DifDiffViewer implements FrameDiffTool.DiffViewer { public void setTitle(String title) { } }); + + myPanel = new JPanel(new BorderLayout()); + myPanel.add(myDirDiffPanel.getPanel(), BorderLayout.CENTER); + DataManager.registerDataProvider(myPanel, new DataProvider() { + @Override + public Object getData(@NonNls String dataId) { + if (PlatformDataKeys.HELP_ID.is(dataId)) { + return "reference.dialogs.diff.folder"; + } + return null; + } + }); } @NotNull @Override public FrameDiffTool.ToolbarComponents init() { - myPanel.setupSplitter(); + myDirDiffPanel.setupSplitter(); return new FrameDiffTool.ToolbarComponents(); } @Override public void dispose() { - Disposer.dispose(myPanel); + Disposer.dispose(myDirDiffPanel); } @NotNull @Override public JComponent getComponent() { - return myPanel.getPanel(); + return myPanel; } @Nullable @Override public JComponent getPreferredFocusedComponent() { - return myPanel.getTable(); + return myDirDiffPanel.getTable(); } // diff --git a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java index 4bdf3d29256f..8e5261256707 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java @@ -38,6 +38,6 @@ public class DirDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Directory Viewer"; + return "Directory viewer"; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java index b94dbefc2b54..881099ae5f91 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java @@ -37,6 +37,6 @@ public class OnesideDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Oneside Viewer"; + return "Oneside viewer"; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java index afae77b20283..7d8bbe4d944a 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java @@ -15,9 +15,6 @@ */ package com.intellij.diff.tools.fragmented; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.hint.HintManagerImpl; -import com.intellij.codeInsight.hint.HintUtil; import com.intellij.diff.DiffContext; import com.intellij.diff.actions.BufferedLineIterator; import com.intellij.diff.actions.NavigationContextChecker; @@ -62,7 +59,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolder; -import com.intellij.ui.LightweightHint; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.MergingCharSequence; @@ -600,14 +596,6 @@ public class OnesideDiffViewer extends TextDiffViewerBase { // private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable { - @Override - public void notify(@NotNull String message) { - final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, myEditor, HintManager.UNDER, HintManager.HIDE_BY_ANY_KEY | - HintManager.HIDE_BY_TEXT_CHANGE | - HintManager.HIDE_BY_SCROLLING, 0, false); - } - @Override public boolean canGoNext() { List diffChanges = getDiffChanges(); @@ -811,6 +799,9 @@ public class OnesideDiffViewer extends TextDiffViewerBase { if (DiffDataKeys.PREV_NEXT_DIFFERENCE_ITERABLE.is(dataId)) { return myPrevNextDifferenceIterable; } + else if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { + return myEditor; + } else { return super.getData(dataId); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java index 8e450792cb30..00ad0ec846e3 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java @@ -38,6 +38,6 @@ public class SimpleDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Default Viewer"; + return "Default viewer"; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java index 3dfbf67b28eb..2fb8519cc716 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java @@ -15,9 +15,6 @@ */ package com.intellij.diff.tools.simple; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.hint.HintManagerImpl; -import com.intellij.codeInsight.hint.HintUtil; import com.intellij.diff.DiffContext; import com.intellij.diff.actions.BufferedLineIterator; import com.intellij.diff.actions.NavigationContextChecker; @@ -57,7 +54,6 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.LightweightHint; import com.intellij.util.Function; import org.jetbrains.annotations.*; @@ -488,16 +484,6 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer { // private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable { - @Override - public void notify(@NotNull String message) { - final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, getCurrentEditor(), HintManager.UNDER, - HintManager.HIDE_BY_ANY_KEY | - HintManager.HIDE_BY_TEXT_CHANGE | - HintManager.HIDE_BY_SCROLLING, - 0, false); - } - @Override public boolean canGoNext() { if (myDiffChanges.isEmpty()) return false; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java index bee26aa522b0..69162f6c3cb8 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java @@ -403,16 +403,6 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer { // private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable { - @Override - public void notify(@NotNull String message) { - final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, getCurrentEditor(), HintManager.UNDER, - HintManager.HIDE_BY_ANY_KEY | - HintManager.HIDE_BY_TEXT_CHANGE | - HintManager.HIDE_BY_SCROLLING, - 0, false); - } - @Override public boolean canGoNext() { if (myDiffChanges.isEmpty()) return false; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java index f4b4391b8d50..e9c274e3ace5 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java @@ -19,9 +19,12 @@ import com.intellij.diff.DiffContext; import com.intellij.diff.FrameDiffTool; import com.intellij.diff.requests.DiffRequest; import com.intellij.openapi.actionSystem.DataKey; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.OpenFileDescriptor; public interface DiffDataKeys { + DataKey CURRENT_EDITOR = DataKey.create("diff_current_editor"); + DataKey DIFF_REQUEST = DataKey.create("diff_request"); DataKey DIFF_CONTEXT = DataKey.create("diff_context"); DataKey DIFF_VIEWER = DataKey.create("diff_frame_viewer"); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java index bbebf841a7e3..dc123ab4ecd9 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java @@ -17,6 +17,7 @@ package com.intellij.diff.tools.util; import com.intellij.openapi.ui.Divider; import com.intellij.openapi.ui.Splitter; +import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,7 +29,7 @@ public class DiffSplitter extends Splitter { @Nullable private Painter myPainter; public DiffSplitter() { - setDividerWidth(30); + setDividerWidth(JBUI.scale(30)); } @Override diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java b/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java index aea7a7f848ae..df9581bbda02 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java @@ -15,11 +15,7 @@ */ package com.intellij.diff.tools.util; -import org.jetbrains.annotations.NotNull; - public interface PrevNextDifferenceIterable { - void notify(@NotNull String message); - boolean canGoPrev(); boolean canGoNext(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java index 69938f66fdad..919832f93386 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java @@ -18,10 +18,10 @@ package com.intellij.diff.tools.util.base; import org.jetbrains.annotations.NotNull; public enum HighlightPolicy { - DO_NOT_HIGHLIGHT("Do Not Highlight"), - BY_LINE("By Line"), - BY_WORD("By Word"), - BY_WORD_SPLIT("By Word In Chunks"); + DO_NOT_HIGHLIGHT("Do not highlight"), + BY_LINE("Highlight words"), + BY_WORD("Highlight lines"), + BY_WORD_SPLIT("Highlight split changes"); @NotNull private final String myText; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java index a2317b3489ed..8c38a2af350c 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java @@ -19,10 +19,10 @@ import com.intellij.diff.comparison.ComparisonPolicy; import org.jetbrains.annotations.NotNull; public enum IgnorePolicy { - DEFAULT("Do Not Ignore"), - TRIM_WHITESPACES("Trim Whitespaces"), - IGNORE_WHITESPACES("Ignore Whitespaces"), - IGNORE_WHITESPACES_CHUNKS("Ignore Whitespaces And Empty Lines"); + DEFAULT("Do not ignore"), + TRIM_WHITESPACES("Trim whitespaces"), + IGNORE_WHITESPACES("Ignore whitespaces"), + IGNORE_WHITESPACES_CHUNKS("Ignore whitespaces and empty lines"); @NotNull private final String myText; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java index a583068b2668..f73a10053abe 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java @@ -31,15 +31,15 @@ import java.util.Map; @State( name = "TextDiffSettings", - storages = {@Storage( - file = DiffUtil.DIFF_CONFIG)}) + storages = @Storage(file = DiffUtil.DIFF_CONFIG) +) public class TextDiffSettingsHolder implements PersistentStateComponent { public static final Key KEY = Key.create("TextDiffSettings"); public static final int[] CONTEXT_RANGE_MODES = {1, 2, 4, 8, -1}; public static final String[] CONTEXT_RANGE_MODE_LABELS = {"1", "2", "4", "8", "Disable"}; - private static class SharedSettings { + private final static class SharedSettings { // Fragments settings public int CONTEXT_RANGE = 4; } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java index eeed7c6800d4..462ecddc6a72 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java @@ -23,6 +23,7 @@ import com.intellij.diff.contents.DocumentContent; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; import com.intellij.diff.requests.SimpleDiffRequest; +import com.intellij.diff.tools.util.DiffDataKeys; import com.intellij.diff.tools.util.SyncScrollSupport; import com.intellij.diff.tools.util.SyncScrollSupport.ThreesideSyncScrollSupport; import com.intellij.diff.tools.util.base.TextDiffViewerBase; @@ -48,6 +49,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.CalledInAwt; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -373,6 +375,15 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase { // Helpers // + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { + return getCurrentEditor(); + } + return super.getData(dataId); + } + @NotNull protected Graphics2D getDividerGraphics(@NotNull Graphics g, @NotNull Component divider) { int width = divider.getWidth(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java index 92143d4dc18b..0e776baa4ab0 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java @@ -23,6 +23,7 @@ import com.intellij.diff.contents.DocumentContent; import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; +import com.intellij.diff.tools.util.DiffDataKeys; import com.intellij.diff.tools.util.SyncScrollSupport; import com.intellij.diff.tools.util.SyncScrollSupport.TwosideSyncScrollSupport; import com.intellij.diff.tools.util.base.TextDiffViewerBase; @@ -48,6 +49,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.CalledInAwt; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -404,6 +406,15 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { // Helpers // + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { + return getCurrentEditor(); + } + return super.getData(dataId); + } + @NotNull protected Graphics2D getDividerGraphics(@NotNull Graphics g, @NotNull Component divider) { assert myEditor1 != null && myEditor2 != null; diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index 591c3c976136..3f79865d3f10 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -57,6 +57,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapperDialog; import com.intellij.openapi.ui.WindowWrapper; import com.intellij.openapi.util.*; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; @@ -78,6 +79,7 @@ import java.awt.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.BitSet; +import java.util.Collections; import java.util.List; public class DiffUtil { @@ -349,8 +351,12 @@ public class DiffUtil { List result = new ArrayList(contents.size()); + if (equalCharsets && equalSeparators && ContainerUtil.find(titles, Condition.NOT_NULL) == null) { + return Collections.nCopies(titles.size(), null); + } + for (int i = 0; i < contents.size(); i++) { - result.add(createTitle(titles.get(i), contents.get(i), equalCharsets, equalSeparators, editors.get(i))); + result.add(createTitle(StringUtil.notNullize(titles.get(i)), contents.get(i), equalCharsets, equalSeparators, editors.get(i))); } return result; diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java index 055fbc8ca6d7..d2f9b41fde60 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java @@ -184,7 +184,7 @@ public class UISettings extends SimpleModificationTracker implements PersistentS public static class FontFilter implements SerializationFilter { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { UISettings settings = (UISettings)bean; return !hasDefaultFontSetting(settings); } diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java index d19658d588fb..085fecc6fae2 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java @@ -18,14 +18,14 @@ package com.intellij.openapi.editor.colors; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.options.Scheme; -import com.intellij.openapi.util.JDOMExternalizable; +import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; -public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, TextAttributesScheme, Scheme { +public interface EditorColorsScheme extends Cloneable, TextAttributesScheme, Scheme { @NonNls String DEFAULT_SCHEME_NAME = "Default"; void setName(String name); @@ -90,4 +90,6 @@ public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, TextA float getConsoleLineSpacing(); void setConsoleLineSpacing(float lineSpacing); + + void readExternal(Element parentNode); } diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java index e98a742e5417..1ef7b91fa454 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.editor.colors; +import com.intellij.util.ObjectUtils; + import java.util.HashMap; import java.util.Map; @@ -37,6 +39,6 @@ public enum EditorFontType { } public static EditorFontType getConsoleType(EditorFontType fontType) { - return ourConsoleTypes.get(fontType); + return ObjectUtils.chooseNotNull(ourConsoleTypes.get(fontType), fontType); } } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java index 53ac33ba72fc..4940473bc740 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,7 +18,6 @@ package com.intellij.openapi.editor.colors.ex; import com.intellij.openapi.components.*; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; -import com.intellij.openapi.util.InvalidDataException; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -28,6 +27,7 @@ import java.util.List; @State( name = "DefaultColorSchemesManager", + defaultStateAsResource = true, storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") ) public class DefaultColorSchemesManager implements PersistentStateComponent { @@ -51,13 +51,8 @@ public class DefaultColorSchemesManager implements PersistentStateComponent CURR_VERSION) throw new InvalidDataException("Unsupported color scheme version: " + readVersion); - myVersion = readVersion; - String isDefaultScheme = node.getAttributeValue(DEFAULT_SCHEME_ATTR); - if (isDefaultScheme == null || !Boolean.parseBoolean(isDefaultScheme)) { - String parentSchemeName = node.getAttributeValue(PARENT_SCHEME_ATTR); - if (parentSchemeName == null) parentSchemeName = DEFAULT_SCHEME_NAME; - myParentScheme = myDefaultColorSchemesManager.getScheme(parentSchemeName); - } - - for (final Object o : node.getChildren()) { - Element childNode = (Element)o; - String childName = childNode.getName(); - if (OPTION_ELEMENT.equals(childName)) { - readSettings(childNode); - } - else if (EDITOR_FONT.equals(childName)) { - readFontSettings(childNode, myFontPreferences); - } - else if (CONSOLE_FONT.equals(childName)) { - readFontSettings(childNode, myConsoleFontPreferences); - } - else if (COLORS_ELEMENT.equals(childName)) { - readColors(childNode); - } - else if (ATTRIBUTES_ELEMENT.equals(childName)) { - readAttributes(childNode); - } - } - - if (myDeprecatedBackgroundColor != null) { - TextAttributes textAttributes = myAttributesMap.get(HighlighterColors.TEXT); - if (textAttributes == null) { - textAttributes = new TextAttributes(Color.black, myDeprecatedBackgroundColor, null, EffectType.BOXED, Font.PLAIN); - myAttributesMap.put(HighlighterColors.TEXT, textAttributes); - } - else { - textAttributes.setBackgroundColor(myDeprecatedBackgroundColor); - } - } - - if (myConsoleFontPreferences.getEffectiveFontFamilies().isEmpty()) { - myFontPreferences.copyTo(myConsoleFontPreferences); - } - - initFonts(); + if (!SCHEME_ELEMENT.equals(node.getName())) { + return; } + + setName(node.getAttributeValue(NAME_ATTR)); + int readVersion = Integer.parseInt(node.getAttributeValue(VERSION_ATTR, "0")); + if (readVersion > CURR_VERSION) { + throw new IllegalStateException("Unsupported color scheme version: " + readVersion); + } + + myVersion = readVersion; + String isDefaultScheme = node.getAttributeValue(DEFAULT_SCHEME_ATTR); + if (isDefaultScheme == null || !Boolean.parseBoolean(isDefaultScheme)) { + myParentScheme = DefaultColorSchemesManager.getInstance().getScheme(node.getAttributeValue(PARENT_SCHEME_ATTR, DEFAULT_SCHEME_NAME)); + } + + for (final Object o : node.getChildren()) { + Element childNode = (Element)o; + String childName = childNode.getName(); + if (OPTION_ELEMENT.equals(childName)) { + readSettings(childNode); + } + else if (EDITOR_FONT.equals(childName)) { + readFontSettings(childNode, myFontPreferences); + } + else if (CONSOLE_FONT.equals(childName)) { + readFontSettings(childNode, myConsoleFontPreferences); + } + else if (COLORS_ELEMENT.equals(childName)) { + readColors(childNode); + } + else if (ATTRIBUTES_ELEMENT.equals(childName)) { + readAttributes(childNode); + } + } + + if (myDeprecatedBackgroundColor != null) { + TextAttributes textAttributes = myAttributesMap.get(HighlighterColors.TEXT); + if (textAttributes == null) { + textAttributes = new TextAttributes(Color.black, myDeprecatedBackgroundColor, null, EffectType.BOXED, Font.PLAIN); + myAttributesMap.put(HighlighterColors.TEXT, textAttributes); + } + else { + textAttributes.setBackgroundColor(myDeprecatedBackgroundColor); + } + } + + if (myConsoleFontPreferences.getEffectiveFontFamilies().isEmpty()) { + myFontPreferences.copyTo(myConsoleFontPreferences); + } + + initFonts(); } - protected void readAttributes(Element childNode) throws InvalidDataException { - for (final Object o : childNode.getChildren(OPTION_ELEMENT)) { - Element e = (Element)o; - String key = e.getAttributeValue(NAME_ATTR); - TextAttributesKey name = TextAttributesKey.find(key); - Element value = e.getChild(VALUE_ELEMENT); - TextAttributes attr = new TextAttributes(value); + protected void readAttributes(@NotNull Element childNode) { + for (Element e : childNode.getChildren(OPTION_ELEMENT)) { + TextAttributesKey name = TextAttributesKey.find(e.getAttributeValue(NAME_ATTR)); + TextAttributes attr = new TextAttributes(e.getChild(VALUE_ELEMENT)); myAttributesMap.put(name, attr); migrateErrorStripeColorFrom45(name, attr); } @@ -446,7 +440,6 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { return value == null ? e.getAttributeValue(VALUE_ELEMENT) : value; } - @Override public void writeExternal(Element parentNode) throws WriteExternalException { parentNode.setAttribute(NAME_ATTR, getName()); parentNode.setAttribute(VERSION_ATTR, Integer.toString(myVersion)); @@ -545,9 +538,8 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { } } - private boolean haveToWrite(final TextAttributesKey key, final TextAttributes value, final TextAttributes defaultAttribute) { - if (key.getFallbackAttributeKey() != null && value.isFallbackEnabled()) return false; - return !value.equals(defaultAttribute); + private static boolean haveToWrite(final TextAttributesKey key, final TextAttributes value, final TextAttributes defaultAttribute) { + return !(key.getFallbackAttributeKey() != null && value.isFallbackEnabled()) && !value.equals(defaultAttribute); } private void writeAttributes(Element attrElements) throws WriteExternalException { diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java index 7c907d1c607b..31ab7469b217 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java @@ -22,9 +22,7 @@ package com.intellij.openapi.editor.colors.impl; import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorFontType; import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.util.InvalidDataException; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,8 +32,8 @@ import java.awt.*; public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnlyColorsScheme { private String myName; - public DefaultColorsScheme(DefaultColorSchemesManager defaultColorSchemesManager) { - super(null, defaultColorSchemesManager); + public DefaultColorsScheme() { + super(null); } @Override @@ -62,7 +60,7 @@ public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnl } @Override - public void readExternal(Element parentNode) throws InvalidDataException { + public void readExternal(Element parentNode) { super.readExternal(parentNode); myName = parentNode.getAttributeValue(NAME_ATTR); } @@ -87,10 +85,9 @@ public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnl @Override public Object clone() { - EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(this, myDefaultColorSchemesManager); + EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(this); copyTo(newScheme); newScheme.setName(DEFAULT_SCHEME_NAME); return newScheme; } - } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java index 1fc6e1fa4f06..16c3592092a2 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java @@ -18,7 +18,6 @@ package com.intellij.openapi.editor.colors.impl; import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.ExternalInfo; import com.intellij.openapi.options.ExternalizableScheme; @@ -34,8 +33,8 @@ import java.awt.*; public class EditorColorsSchemeImpl extends AbstractColorsScheme implements ExternalizableScheme { private final ExternalInfo myExternalInfo = new ExternalInfo(); - public EditorColorsSchemeImpl(EditorColorsScheme parentScheme, DefaultColorSchemesManager defaultColorSchemesManager) { - super(parentScheme, defaultColorSchemesManager); + public EditorColorsSchemeImpl(EditorColorsScheme parentScheme) { + super(parentScheme); } @Override @@ -69,7 +68,6 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte return myParentScheme.getAttributes(key); } - public boolean containsKey(TextAttributesKey key) { return myAttributesMap.containsKey(key); } @@ -87,7 +85,7 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte @Override public Object clone() { - EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(myParentScheme, DefaultColorSchemesManager.getInstance()); + EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(myParentScheme); copyTo(newScheme); newScheme.setName(getName()); return newScheme; diff --git a/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java b/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java index 2e2f12af1d0f..4aca7d3abec8 100644 --- a/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java +++ b/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java @@ -18,6 +18,7 @@ package com.intellij.lang; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Implementers of the interface encapsulate optimize imports process for the language. @@ -50,4 +51,11 @@ public interface ImportOptimizer { @NotNull Runnable processFile(PsiFile file); + /** + * In order to customize notification popup after reformat code action just return it from {@link #processFile} with proper information, + * by default "imports optimized" is shown. + */ + interface CollectingInfoRunnable extends Runnable { + @Nullable String getUserNotificationInfo(); + } } diff --git a/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java b/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java index e9e72103f612..5eb526877ba6 100644 --- a/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java +++ b/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java @@ -20,7 +20,6 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.EditorColorsUtil; -import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.ui.UIUtil; @@ -51,10 +50,9 @@ public class UsageTreeColorsScheme implements NamedComponent, JDOMExternalizable } @Override - public void readExternal(Element element) throws InvalidDataException { + public void readExternal(Element element) { if (myColorsScheme == null) { - EditorColorsScheme scheme = EditorColorsUtil.getColorSchemeForBackground(UIUtil.getTreeTextBackground()); - myColorsScheme = (EditorColorsScheme)scheme.clone(); + myColorsScheme = (EditorColorsScheme)EditorColorsUtil.getColorSchemeForBackground(UIUtil.getTreeTextBackground()).clone(); } myColorsScheme.readExternal(element); } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java index 843f8880d713..959bcf75e7d2 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -61,6 +62,13 @@ public class RearrangeCodeAction extends AnAction { if (file == null) { return; } - new RearrangeCodeProcessor(project, file, editor.getSelectionModel()).run(); + + SelectionModel model = editor.getSelectionModel(); + if (model.hasSelection()) { + new RearrangeCodeProcessor(file, model).run(); + } + else { + new RearrangeCodeProcessor(file).run(); + } } } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index dff0a5c4eac8..bda2aab689ba 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -32,7 +32,6 @@ import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl; import com.intellij.openapi.editor.colors.impl.ReadOnlyColorsScheme; @@ -990,7 +989,8 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract private boolean myIsNew = false; private MyColorScheme(@NotNull EditorColorsScheme parentScheme) { - super(parentScheme, DefaultColorSchemesManager.getInstance()); + super(parentScheme); + parentScheme.getFontPreferences().copyTo(getFontPreferences()); setLineSpacing(parentScheme.getLineSpacing()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index e2447f775f6a..5613b489e71c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -18,12 +18,16 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.lang.LanguageFormatting; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProcessCanceledException; @@ -37,6 +41,7 @@ import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.roots.GeneratedSourcesFilter; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ex.MessagesEx; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiBundle; import com.intellij.psi.PsiDirectory; @@ -45,7 +50,9 @@ import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SequentialModalProgressTask; import com.intellij.util.SequentialTask; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,12 +76,14 @@ public abstract class AbstractLayoutCodeProcessor { private final String myProgressText; private final String myCommandName; - private final Runnable myPostRunnable; + private Runnable myPostRunnable; private boolean myProcessChangedTextOnly; protected AbstractLayoutCodeProcessor myPreviousCodeProcessor; private List myFilters = ContainerUtil.newArrayList(); + private LayoutCodeInfoCollector myInfoCollector; + protected AbstractLayoutCodeProcessor(Project project, String commandName, String progressText, boolean processChangedTextOnly) { this(project, (Module)null, commandName, progressText, processChangedTextOnly); } @@ -96,6 +105,7 @@ public abstract class AbstractLayoutCodeProcessor { myCommandName = commandName; myPreviousCodeProcessor = previous; myFilters = previous.myFilters; + myInfoCollector = previous.myInfoCollector; } protected AbstractLayoutCodeProcessor(Project project, @@ -171,12 +181,26 @@ public abstract class AbstractLayoutCodeProcessor { return list; } + public void setPostRunnable(Runnable postRunnable) { + myPostRunnable = postRunnable; + } + @Nullable private FutureTask getPreviousProcessorTask(@NotNull PsiFile file, boolean processChangedTextOnly) { return myPreviousCodeProcessor != null ? myPreviousCodeProcessor.preprocessFile(file, processChangedTextOnly) : null; } + public void setCollectInfo(boolean isCollectInfo) { + myInfoCollector = isCollectInfo ? new LayoutCodeInfoCollector() : null; + + AbstractLayoutCodeProcessor current = this; + while (current.myPreviousCodeProcessor != null) { + current = current.myPreviousCodeProcessor; + current.myInfoCollector = myInfoCollector; + } + } + public void addFileFilter(@NotNull FileFilter filter) { myFilters.add(filter); } @@ -584,4 +608,37 @@ public abstract class AbstractLayoutCodeProcessor { return true; } + + protected static List getSelectedRanges(@NotNull SelectionModel selectionModel) { + final List ranges = new SmartList(); + if (selectionModel.hasSelection()) { + TextRange range = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); + ranges.add(range); + } + else if (selectionModel.hasBlockSelection()) { + int[] starts = selectionModel.getBlockSelectionStarts(); + int[] ends = selectionModel.getBlockSelectionEnds(); + for (int i = 0; i < starts.length; i++) { + ranges.add(TextRange.create(starts[i], ends[i])); + } + } + + return ranges; + } + + protected void handleFileTooBigException(Logger logger, FilesTooBigForDiffException e, @NotNull PsiFile file) { + logger.info("Error while calculating changed ranges for: " + file.getVirtualFile(), e); + if (!ApplicationManager.getApplication().isUnitTestMode()) { + Notification notification = new Notification(ApplicationBundle.message("reformat.changed.text.file.too.big.notification.groupId"), + ApplicationBundle.message("reformat.changed.text.file.too.big.notification.title"), + ApplicationBundle.message("reformat.changed.text.file.too.big.notification.text", file.getName()), + NotificationType.INFORMATION); + notification.notify(file.getProject()); + } + } + + @Nullable + public LayoutCodeInfoCollector getInfoCollector() { + return myInfoCollector; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java new file mode 100644 index 000000000000..75f4c1f3c92e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -0,0 +1,206 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.actions; + +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.hint.HintManagerImpl; +import com.intellij.codeInsight.hint.HintUtil; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; +import com.intellij.ui.ColorUtil; +import com.intellij.ui.JBColor; +import com.intellij.ui.LightweightHint; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +import static com.intellij.codeInsight.actions.TextRangeType.*; + +class FileInEditorProcessor { + private static final Logger LOG = Logger.getInstance(FileInEditorProcessor.class); + + private final Editor myEditor; + + private boolean myNoChangesDetected = false; + private final boolean myProcessChangesTextOnly; + + private final boolean myShouldOptimizeImports; + private final boolean myShouldRearrangeCode; + private final boolean myProcessSelectedText; + + private final Project myProject; + + private final PsiFile myFile; + private AbstractLayoutCodeProcessor myProcessor; + + public FileInEditorProcessor(PsiFile file, + Editor editor, + LayoutCodeOptions runOptions) + { + myFile = file; + myProject = file.getProject(); + myEditor = editor; + + myShouldOptimizeImports = runOptions.isOptimizeImports(); + myShouldRearrangeCode = runOptions.isRearrangeCode(); + myProcessSelectedText = myEditor != null && runOptions.getTextRangeType() == SELECTED_TEXT; + myProcessChangesTextOnly = runOptions.getTextRangeType() == VCS_CHANGED_TEXT; + } + + public void processCode() { + if (myShouldOptimizeImports) { + myProcessor = new OptimizeImportsProcessor(myProject, myFile); + } + + if (myProcessChangesTextOnly && !FormatChangedTextUtil.hasChanges(myFile)) { + myNoChangesDetected = true; + } + + myProcessor = mixWithReformatProcessor(myProcessor); + if (myShouldRearrangeCode) { + myProcessor = mixWithRearrangeProcessor(myProcessor); + } + + if (shouldNotify()) { + myProcessor.setCollectInfo(true); + myProcessor.setPostRunnable(new Runnable() { + @Override + public void run() { + String message = prepareMessage(); + if (!myEditor.isDisposed() && myEditor.getComponent().isShowing()) { + showHint(myEditor, message); + } + } + }); + } + + myProcessor.run(); + } + + private AbstractLayoutCodeProcessor mixWithRearrangeProcessor(@NotNull AbstractLayoutCodeProcessor processor) { + if (myProcessSelectedText) { + processor = new RearrangeCodeProcessor(processor, myEditor.getSelectionModel()); + } + else { + processor = new RearrangeCodeProcessor(processor); + } + return processor; + } + + @NotNull + private AbstractLayoutCodeProcessor mixWithReformatProcessor(@Nullable AbstractLayoutCodeProcessor processor) { + if (processor != null) { + if (myProcessSelectedText) { + processor = new ReformatCodeProcessor(processor, myEditor.getSelectionModel()); + } + else { + processor = new ReformatCodeProcessor(processor, myProcessChangesTextOnly); + } + } + else { + if (myProcessSelectedText) { + processor = new ReformatCodeProcessor(myFile, myEditor.getSelectionModel()); + } + else { + processor = new ReformatCodeProcessor(myFile, myProcessChangesTextOnly); + } + } + return processor; + } + + @NotNull + private String prepareMessage() { + StringBuilder builder = new StringBuilder(""); + LayoutCodeInfoCollector notifications = myProcessor.getInfoCollector(); + LOG.assertTrue(notifications != null); + + if (notifications.isEmpty() && !myNoChangesDetected) { + if (myProcessChangesTextOnly) { + builder.append("No lines changed: changes since last revision are already properly formatted").append("
"); + } + else { + builder.append("No lines changed: code is already properly formatted").append("
"); + } + } + else { + if (notifications.hasReformatOrRearrangeNotification()) { + String reformatInfo = notifications.getReformatCodeNotification(); + String rearrangeInfo = notifications.getRearrangeCodeNotification(); + + builder.append(joinWithCommaAndCapitalize(reformatInfo, rearrangeInfo)); + + if (myProcessChangesTextOnly) { + builder.append(" in changes since last revision"); + } + + builder.append("
"); + } + else if (myNoChangesDetected) { + builder.append("No lines changed: no changes since last revision").append("
"); + } + + String optimizeImportsNotification = notifications.getOptimizeImportsNotification(); + if (optimizeImportsNotification != null) { + builder.append(StringUtil.capitalize(optimizeImportsNotification)).append("
"); + } + } + + String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ShowReformatFileDialog")); + String color = ColorUtil.toHex(JBColor.gray); + + builder.append("") + .append("Show reformat dialog: ").append(shortcutText).append("") + .append(""); + + return builder.toString(); + } + + @NotNull + private String joinWithCommaAndCapitalize(String reformatNotification, String rearrangeNotification) { + String firstNotificationLine = reformatNotification != null ? reformatNotification : rearrangeNotification; + if (reformatNotification != null && rearrangeNotification != null) { + firstNotificationLine += ", " + rearrangeNotification; + } + firstNotificationLine = StringUtil.capitalize(firstNotificationLine); + return firstNotificationLine; + } + + private static void showHint(@NotNull Editor editor, @NotNull String info) { + JComponent component = HintUtil.createInformationLabel(info); + LightweightHint hint = new LightweightHint(component); + HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, + HintManager.HIDE_BY_ANY_KEY | + HintManager.HIDE_BY_TEXT_CHANGE | + HintManager.HIDE_BY_SCROLLING, + 0, false); + } + + private boolean shouldNotify() { + Application application = ApplicationManager.getApplication(); + if (application.isUnitTestMode() || application.isHeadlessEnvironment()) { + return false; + } + return myEditor != null && !myProcessSelectedText; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index 03691d0749e0..0fe2e90f25c7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -54,9 +54,10 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class FormatChangedTextUtil { - public static final Key TEST_REVISION_CONTENT = Key.create("test.revision.content"); + public static final Key TEST_REVISION_CONTENT = Key.create("test.revision.content"); private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.FormatChangedTextUtil"); + private FormatChangedTextUtil() { } @@ -71,26 +72,9 @@ public class FormatChangedTextUtil { final VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile != null) { final Change change = ChangeListManager.getInstance(project).getChange(virtualFile); - if (change != null && change.getType() == Change.Type.NEW) { - return true; - } + return change != null; } - - final LineStatusTrackerManagerI manager = LineStatusTrackerManager.getInstance(project); - if (manager == null) { - return false; - } - - final Document document = PsiDocumentManager.getInstance(project).getDocument(file); - if (document == null) { - return false; - } - final LineStatusTracker lineStatusTracker = manager.getLineStatusTracker(document); - if (lineStatusTracker == null) { - return false; - } - final List ranges = lineStatusTracker.getRanges(); - return !ranges.isEmpty(); + return false; } /** @@ -249,15 +233,18 @@ public class FormatChangedTextUtil { @NotNull public static List getChangedTextRanges(@NotNull Project project, @NotNull PsiFile file) throws FilesTooBigForDiffException { - List cachedChangedLines = getCachedChangedLines(project, file); + Document document = PsiDocumentManager.getInstance(project).getDocument(file); + if (document == null) return ContainerUtil.emptyList(); + + List cachedChangedLines = getCachedChangedLines(project, document); if (cachedChangedLines != null) { return cachedChangedLines; } if (ApplicationManager.getApplication().isUnitTestMode()) { - String testContent = file.getUserData(TEST_REVISION_CONTENT); + CharSequence testContent = file.getUserData(TEST_REVISION_CONTENT); if (testContent != null) { - return calculateChangedTextRanges(file.getProject(), file, testContent); + return calculateChangedTextRanges(document, testContent); } } @@ -270,17 +257,12 @@ public class FormatChangedTextUtil { } String contentFromVcs = getRevisionedContentFrom(change); - return contentFromVcs != null ? calculateChangedTextRanges(project, file, contentFromVcs) + return contentFromVcs != null ? calculateChangedTextRanges(document, contentFromVcs) : ContainerUtil.emptyList(); } @Nullable - private static List getCachedChangedLines(@NotNull Project project, @NotNull PsiFile file) { - Document document = PsiDocumentManager.getInstance(project).getDocument(file); - if (document == null) { - return ContainerUtil.emptyList(); - } - + private static List getCachedChangedLines(@NotNull Project project, @NotNull Document document) { LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(document); if (tracker != null) { List ranges = tracker.getRanges(); @@ -307,19 +289,49 @@ public class FormatChangedTextUtil { } @NotNull - private static List calculateChangedTextRanges(@NotNull Project project, - @NotNull PsiFile file, - @NotNull String contentFromVcs) throws FilesTooBigForDiffException + protected static List calculateChangedTextRanges(@NotNull Document document, + @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException + { + return getChangedTextRanges(document, getRanges(document, contentFromVcs)); + } + + @NotNull + private static List getRanges(@NotNull Document document, + @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException { Document documentFromVcs = ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(contentFromVcs, true, false); - Document document = PsiDocumentManager.getInstance(project).getDocument(file); + return new RangesBuilder(document, documentFromVcs).getRanges(); + } - if (document == null) { - return ContainerUtil.emptyList(); + protected static int calculateChangedLinesNumber(@NotNull Document document, @NotNull CharSequence contentFromVcs) { + try { + List changedRanges = getRanges(document, contentFromVcs); + int linesChanges = 0; + for (Range range : changedRanges) { + linesChanges += countLines(range); + } + return linesChanges; + } catch (FilesTooBigForDiffException e) { + LOG.info("File too big, can not calculate changed lines number"); + return -1; + } + } + + private static int countLines(Range range) { + byte rangeType = range.getType(); + if (rangeType == Range.MODIFIED) { + int currentChangedLines = range.getLine2() - range.getLine1(); + int revisionLinesChanged = range.getVcsLine2() - range.getVcsLine1(); + return Math.max(currentChangedLines, revisionLinesChanged); + } + else if (rangeType == Range.DELETED) { + return range.getVcsLine2() - range.getVcsLine1(); + } + else if (rangeType == Range.INSERTED) { + return range.getLine2() - range.getLine1(); } - List changedRanges = new RangesBuilder(document, documentFromVcs).getRanges(); - return getChangedTextRanges(document, changedRanges); + return 0; } @NotNull diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java new file mode 100644 index 000000000000..9ba882fba3e3 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.actions; + +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.lang.Language; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +public class LastRunReformatCodeOptionsProvider { + + private static final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports"; + private static final String REARRANGE_ENTRIES_KEY = "LayoutCode.rearrangeEntries"; + private static final String PROCESS_CHANGED_TEXT_KEY = "LayoutCode.processChangedText"; + + private final PropertiesComponent myPropertiesComponent; + + public LastRunReformatCodeOptionsProvider(@NotNull PropertiesComponent propertiesComponent) { + myPropertiesComponent = propertiesComponent; + } + + public ReformatCodeRunOptions getLastRunOptions(@NotNull PsiFile file) { + Language language = file.getLanguage(); + + ReformatCodeRunOptions settings = new ReformatCodeRunOptions(getLastTextRangeType()); + settings.setOptimizeImports(getLastOptimizeImports()); + settings.setRearrangeCode(isRearrangeCode(language)); + + return settings; + } + + public void saveRearrangeState(@NotNull Language language, boolean value) { + String key = getRearrangeCodeKeyFor(language); + myPropertiesComponent.setValue(key, Boolean.toString(value)); + } + + public void saveOptimizeImportsState(boolean value) { + String optimizeImports = Boolean.toString(value); + myPropertiesComponent.setValue(OPTIMIZE_IMPORTS_KEY, optimizeImports); + } + + public boolean getLastOptimizeImports() { + return myPropertiesComponent.getBoolean(OPTIMIZE_IMPORTS_KEY, false); + } + + public TextRangeType getLastTextRangeType() { + return myPropertiesComponent.getBoolean(PROCESS_CHANGED_TEXT_KEY, false) ? TextRangeType.VCS_CHANGED_TEXT : TextRangeType.WHOLE_FILE; + } + + public void saveProcessVcsChangedTextState(boolean value) { + String processOnlyVcsChangedText = Boolean.toString(value); + myPropertiesComponent.setValue(PROCESS_CHANGED_TEXT_KEY, processOnlyVcsChangedText); + } + + public void saveRearrangeCodeState(boolean value) { + myPropertiesComponent.setValue(REARRANGE_ENTRIES_KEY, Boolean.toString(value)); + } + + public boolean getLastRearrangeCode() { + return myPropertiesComponent.getBoolean(REARRANGE_ENTRIES_KEY, false); + } + + public boolean isRearrangeCode(@NotNull Language language) { + String key = getRearrangeCodeKeyFor(language); + return myPropertiesComponent.getBoolean(key, false); + } + + private static String getRearrangeCodeKeyFor(@NotNull Language language) { + return REARRANGE_ENTRIES_KEY + language.getDisplayName(); + } + +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form new file mode 100644 index 000000000000..3c6a16512e86 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form @@ -0,0 +1,135 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 716d2f884844..cd0a9c0890f2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -16,279 +16,176 @@ package com.intellij.codeInsight.actions; -import com.intellij.CommonBundle; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.LanguageImportStatements; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.arrangement.Rearranger; -import com.intellij.psi.search.SearchScope; +import com.intellij.testFramework.LightVirtualFile; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions { +public class LayoutCodeDialog extends DialogWrapper { @NotNull private final Project myProject; - @Nullable private final PsiFile myFile; - @Nullable private final PsiDirectory myDirectory; - private final Boolean myTextSelected; + @NotNull private final PsiFile myFile; - private JRadioButton myRbFile; - private JRadioButton myRbSelectedText; - private JRadioButton myRbDirectory; - private JCheckBox myCbIncludeSubdirs; - private JCheckBox myCbOptimizeImports; - private JCheckBox myCbArrangeEntries; - private JCheckBox myCbOnlyVcsChangedRegions; - private JCheckBox myDoNotAskMeCheckBox; + private final boolean myTextSelected; private final String myHelpId; - @Nullable private CommonCodeStyleSettings myCommonSettings; - private boolean myRearrangeAlwaysEnabled; + private final LastRunReformatCodeOptionsProvider myLastRunOptions; - private final boolean myOptimizeImportProcessorsForFileLanguageExists; - private final boolean myRearrangerProcessorsForFileLanguageExists; - private final boolean myFileHasChanges; + private JPanel myButtonsPanel; - private boolean myOptimizeImportsSelected; - private boolean myFormatOnlyVCSChangedRegionsSelected; - private boolean myDoNotShowDialogSelected; - private boolean myRearrangeEntriesSelected; + private JCheckBox myOptimizeImportsCb; + private JCheckBox myRearrangeCodeCb; + private JRadioButton myOnlyVCSChangedTextRb; + private JRadioButton mySelectedTextRadioButton; + private JRadioButton myWholeFileRadioButton; - public LayoutCodeDialog(@NotNull Project project, - @NotNull String title, - @Nullable PsiFile file, - @Nullable PsiDirectory directory, - Boolean isTextSelected, + private JPanel myActionsPanel; + private JPanel myScopePanel; + private JLabel myOptionalLabel; + + private LayoutCodeOptions myRunOptions; + + public LayoutCodeDialog(@NotNull Project project, + @NotNull PsiFile file, + boolean textSelected, final String helpId) { super(project, true); myFile = file; myProject = project; - myDirectory = directory; - myTextSelected = isTextSelected; + myTextSelected = textSelected; + myHelpId = helpId; - myOptimizeImportProcessorsForFileLanguageExists = myFile != null && !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty(); - myRearrangerProcessorsForFileLanguageExists = myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; - myFileHasChanges = myFile != null && FormatChangedTextUtil.hasChanges(myFile); - - if (myFile != null) myCommonSettings = CodeStyleSettingsManager.getSettings(myProject).getCommonSettings(myFile.getLanguage()); - myRearrangeAlwaysEnabled = myCommonSettings != null - && myCommonSettings.isForceArrangeMenuAvailable() - && myCommonSettings.FORCE_REARRANGE_MODE == CommonCodeStyleSettings.REARRANGE_ALWAYS; + myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + myRunOptions = createOptionsBundledOnDialog(); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); - setTitle(title); + setTitle("Reformat File: " + file.getName()); + init(); - myHelpId = helpId; } - @Override protected void init() { super.init(); - loadCbsStates(); - setUpInitialSelection(); - - myRbFile.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - saveEnabledCbsSelectedState(); - setUpCbsStateForFileFormatting(); - } - }); - - myRbDirectory.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - saveEnabledCbsSelectedState(); - setUpCbsStatesForDirectoryFormatting(); - } - }); - - myRbSelectedText.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - saveEnabledCbsSelectedState(); - setUpCbsStatesForSelectedTextFormatting(); - } - }); + setUpActions(); + setUpTextRangeMode(); } - private void setUpInitialSelection() { - if (myTextSelected == Boolean.TRUE) { - myRbSelectedText.setSelected(true); - setUpCbsStatesForSelectedTextFormatting(); + + private void setUpTextRangeMode() { + mySelectedTextRadioButton.setEnabled(myTextSelected); + if (!myTextSelected) { + mySelectedTextRadioButton.setToolTipText("No text selected in editor"); + } + + final boolean fileHasChanges = FormatChangedTextUtil.hasChanges(myFile); + if (myFile.getVirtualFile() instanceof LightVirtualFile) { + myOnlyVCSChangedTextRb.setVisible(false); } else { - if (myFile != null) { - myRbFile.setSelected(true); - setUpCbsStateForFileFormatting(); + myOnlyVCSChangedTextRb.setEnabled(fileHasChanges); + if (!fileHasChanges) { + String hint = getChangesNotAvailableHint(); + if (hint != null) myOnlyVCSChangedTextRb.setToolTipText(hint); + } + } + + myWholeFileRadioButton.setEnabled(true); + + if (myTextSelected) { + mySelectedTextRadioButton.setSelected(true); + } + else { + boolean lastRunProcessedChangedText = myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; + if (lastRunProcessedChangedText && fileHasChanges) { + myOnlyVCSChangedTextRb.setSelected(true); } else { - myRbDirectory.setSelected(true); - setUpCbsStatesForDirectoryFormatting(); + myWholeFileRadioButton.setSelected(true); } } - myCbIncludeSubdirs.setSelected(true); } - private void loadCbsStates() { - myOptimizeImportsSelected = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false); - myRearrangeEntriesSelected = myRearrangeAlwaysEnabled || ReformatCodeAction.getLastSavedRearrangeCbState(myProject, myFile); - myFormatOnlyVCSChangedRegionsSelected = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); + private void setUpActions() { + boolean canOptimizeImports = !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty(); + myOptimizeImportsCb.setVisible(canOptimizeImports); + if (canOptimizeImports) { + myOptimizeImportsCb.setSelected(myLastRunOptions.getLastOptimizeImports()); + } + + boolean canRearrangeCode = Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; + myRearrangeCodeCb.setVisible(canRearrangeCode); + if (canRearrangeCode) { + myRearrangeCodeCb.setSelected(myLastRunOptions.isRearrangeCode(myFile.getLanguage())); + } + + myOptionalLabel.setVisible(canOptimizeImports || canRearrangeCode); } - private void saveEnabledCbsSelectedState() { - if (myCbArrangeEntries.isEnabled()) { - myRearrangeEntriesSelected = myCbArrangeEntries.isSelected(); + @Nullable + private String getChangesNotAvailableHint() { + if (!VcsUtil.isFileUnderVcs(myProject, VcsUtil.getFilePath(myFile.getVirtualFile()))) { + return "File not under VCS root"; } - if (myCbOptimizeImports.isEnabled()) { - myOptimizeImportsSelected = myCbOptimizeImports.isSelected(); + else if (!FormatChangedTextUtil.hasChanges(myFile)) { + return "File was not changed since last revision"; } - if (myCbOnlyVcsChangedRegions.isEnabled()) { - myFormatOnlyVCSChangedRegionsSelected = myCbOnlyVcsChangedRegions.isSelected(); + return null; + } + + private void saveCurrentConfiguration() { + if (myOptimizeImportsCb.isEnabled()) { + myLastRunOptions.saveOptimizeImportsState(myRunOptions.isOptimizeImports()); } - if (myDoNotAskMeCheckBox.isEnabled()) { - myDoNotShowDialogSelected = myDoNotAskMeCheckBox.isSelected(); + if (myRearrangeCodeCb.isEnabled()) { + myLastRunOptions.saveRearrangeState(myFile.getLanguage(), myRunOptions.isRearrangeCode()); + } + + if (!mySelectedTextRadioButton.isSelected()) { + myLastRunOptions.saveProcessVcsChangedTextState(myOnlyVCSChangedTextRb.isSelected()); } } - private void setUpCbsStateForFileFormatting() { - myCbOptimizeImports.setEnabled(myOptimizeImportProcessorsForFileLanguageExists); - myCbOptimizeImports.setSelected(myOptimizeImportProcessorsForFileLanguageExists && myOptimizeImportsSelected); + @NotNull + private LayoutCodeOptions createOptionsBundledOnDialog() { + return new LayoutCodeOptions() { + @Override + public TextRangeType getTextRangeType() { + if (myOnlyVCSChangedTextRb.isSelected()) { + return TextRangeType.VCS_CHANGED_TEXT; + } + if (mySelectedTextRadioButton.isSelected()) { + return TextRangeType.SELECTED_TEXT; + } + return TextRangeType.WHOLE_FILE; + } - myCbArrangeEntries.setEnabled(myRearrangerProcessorsForFileLanguageExists); - myCbArrangeEntries.setSelected(myRearrangerProcessorsForFileLanguageExists && myRearrangeEntriesSelected); + @Override + public boolean isRearrangeCode() { + return myRearrangeCodeCb.isEnabled() && myRearrangeCodeCb.isSelected(); + } - myCbOnlyVcsChangedRegions.setEnabled(myFileHasChanges); - myCbOnlyVcsChangedRegions.setSelected(myFileHasChanges && myFormatOnlyVCSChangedRegionsSelected); - - myDoNotAskMeCheckBox.setEnabled(true); - myDoNotAskMeCheckBox.setSelected(myDoNotShowDialogSelected); - - myCbIncludeSubdirs.setEnabled(false); - } - - private void setUpCbsStatesForDirectoryFormatting() { - myCbOptimizeImports.setEnabled(true); - myCbOptimizeImports.setSelected(myOptimizeImportsSelected); - - myCbArrangeEntries.setEnabled(true); - myCbArrangeEntries.setSelected(myRearrangeEntriesSelected); - - myCbOnlyVcsChangedRegions.setEnabled(myDirectory != null && FormatChangedTextUtil.hasChanges(myDirectory)); - myCbOnlyVcsChangedRegions.setSelected(false); - - myDoNotAskMeCheckBox.setEnabled(false); - myDoNotAskMeCheckBox.setSelected(false); - - myCbIncludeSubdirs.setEnabled(true); - } - - private void setUpCbsStatesForSelectedTextFormatting() { - myCbOptimizeImports.setEnabled(false); - myCbOptimizeImports.setSelected(false); - - myCbArrangeEntries.setEnabled(true); - myCbArrangeEntries.setSelected(myRearrangeEntriesSelected); - - myCbOnlyVcsChangedRegions.setEnabled(false); - myCbOnlyVcsChangedRegions.setSelected(false); - - myDoNotAskMeCheckBox.setEnabled(true); - myDoNotAskMeCheckBox.setSelected(myDoNotShowDialogSelected); - - myCbIncludeSubdirs.setEnabled(false); + @Override + public boolean isOptimizeImports() { + return myOptimizeImportsCb.isEnabled() && myOptimizeImportsCb.isSelected(); + } + }; } + @Nullable @Override protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new GridBagLayout()); - panel.setBorder(BorderFactory.createEmptyBorder(4, 8, 8, 0)); - GridBagConstraints gbConstraints = new GridBagConstraints(); - gbConstraints.gridy = 0; - gbConstraints.gridx = 0; - gbConstraints.gridwidth = 3; - gbConstraints.gridheight = 1; - gbConstraints.weightx = 1; - - gbConstraints.fill = GridBagConstraints.BOTH; - gbConstraints.insets = new Insets(0, 0, 0, 0); - - myRbFile = new JRadioButton(CodeInsightBundle.message("process.scope.file", - (myFile != null ? "'" + myFile.getVirtualFile().getPresentableUrl() + "'" : ""))); - panel.add(myRbFile, gbConstraints); - - myRbSelectedText = new JRadioButton(CodeInsightBundle.message("reformat.option.selected.text")); - if (myTextSelected != null) { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myRbSelectedText, gbConstraints); - } - - myRbDirectory = new JRadioButton(); - myCbIncludeSubdirs = new JCheckBox(CodeInsightBundle.message("reformat.option.include.subdirectories")); - if (myDirectory != null) { - myRbDirectory.setText(CodeInsightBundle.message("reformat.option.all.files.in.directory", - myDirectory.getVirtualFile().getPresentableUrl())); - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myRbDirectory, gbConstraints); - - if (myDirectory.getSubdirectories().length > 0) { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 20, 0, 0); - panel.add(myCbIncludeSubdirs, gbConstraints); - } - } - - myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports")); - if (myTextSelected != null && LanguageImportStatements.INSTANCE.hasAnyExtensions()) { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myCbOptimizeImports, gbConstraints); - } - - myCbArrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries")); - if (myDirectory != null || myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null) - { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myCbArrangeEntries, gbConstraints); - } - - myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region")); - gbConstraints.gridy++; - panel.add(myCbOnlyVcsChangedRegions, gbConstraints); - - ButtonGroup buttonGroup = new ButtonGroup(); - buttonGroup.add(myRbFile); - buttonGroup.add(myRbSelectedText); - buttonGroup.add(myRbDirectory); - - myRbFile.setEnabled(myFile != null); - myRbSelectedText.setEnabled(myTextSelected == Boolean.TRUE); - - return panel; - } - - @Override - protected JComponent createSouthPanel() { - JComponent southPanel = super.createSouthPanel(); - myDoNotAskMeCheckBox = new JCheckBox(CommonBundle.message("dialog.options.do.not.show")); - return DialogWrapper.addDoNotShowCheckBox(southPanel, myDoNotAskMeCheckBox); + return myButtonsPanel; } @NotNull @@ -302,81 +199,14 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions HelpManager.getInstance().invokeHelp(myHelpId); } - @Override - public boolean isProcessWholeFile() { - return myRbFile.isSelected(); - } - - @Override - public boolean isProcessDirectory() { - return myRbDirectory.isSelected(); - } - - @Override - public boolean isIncludeSubdirectories() { - return myCbIncludeSubdirs.isSelected(); - } - - @Override - public boolean isOptimizeImports() { - return myCbOptimizeImports.isSelected(); - } - - @Override - public boolean isRearrangeEntries() { - return myCbArrangeEntries.isSelected(); - } - - @Nullable - @Override - public String getFileTypeMask() { - return null; - } - - @Nullable - @Override - public SearchScope getSearchScope() { - return null; - } - - @Override - public boolean isProcessOnlyChangedText() { - return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected(); - } - - public boolean isDoNotAskMe() { - if (myDoNotAskMeCheckBox.isEnabled()) { - return myDoNotAskMeCheckBox.isSelected(); - } - else { - return !EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG; - } - } - @Override protected void doOKAction() { super.doOKAction(); - persistEnabledCbsStates(); + saveCurrentConfiguration(); } - private void persistEnabledCbsStates() { - if (myCbOptimizeImports.isEnabled()) { - String optimizeImports = Boolean.toString(myCbOptimizeImports.isSelected()); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, optimizeImports); - } - if (myCbOnlyVcsChangedRegions.isEnabled()) { - String formatVcsChangedRegions = Boolean.toString(myCbOnlyVcsChangedRegions.isSelected()); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, formatVcsChangedRegions); - } - if (myCbArrangeEntries.isEnabled()) { - saveRearrangeCbState(myCbArrangeEntries.isSelected()); - } + public LayoutCodeOptions getRunOptions() { + return myRunOptions; } - private void saveRearrangeCbState(boolean isSelected) { - if (myFile != null) - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, myFile.getLanguage(), isSelected); - else - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isSelected); - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeInfoCollector.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeInfoCollector.java new file mode 100644 index 000000000000..8fc7a60d87d1 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeInfoCollector.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2015 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.actions; + +public class LayoutCodeInfoCollector { + + private String optimizeImportsNotification = null; + private String reformatCodeNotification = null; + private String rearrangeCodeNotification = null; + + public String getOptimizeImportsNotification() { + return optimizeImportsNotification; + } + + public void setOptimizeImportsNotification(String optimizeImportsNotification) { + this.optimizeImportsNotification = optimizeImportsNotification; + } + + public String getReformatCodeNotification() { + return reformatCodeNotification; + } + + public void setReformatCodeNotification(String reformatCodeNotification) { + this.reformatCodeNotification = reformatCodeNotification; + } + + public String getRearrangeCodeNotification() { + return rearrangeCodeNotification; + } + + public void setRearrangeCodeNotification(String rearrangeCodeNotification) { + this.rearrangeCodeNotification = rearrangeCodeNotification; + } + + public boolean hasReformatOrRearrangeNotification() { + return rearrangeCodeNotification != null + || reformatCodeNotification != null; + } + + public boolean isEmpty() { + return optimizeImportsNotification == null + && rearrangeCodeNotification == null + && reformatCodeNotification == null; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java index 5a05a9ac13ab..2400e3b628af 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java @@ -15,10 +15,14 @@ */ package com.intellij.codeInsight.actions; -public interface LayoutCodeOptions extends DirectoryFormattingOptions { +public interface LayoutCodeOptions extends OptionalReformatActions { - boolean isProcessWholeFile(); - - boolean isProcessDirectory(); + TextRangeType getTextRangeType(); } + +enum TextRangeType { + VCS_CHANGED_TEXT, + SELECTED_TEXT, + WHOLE_FILE +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java deleted file mode 100644 index 5175cf522556..000000000000 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2000-2013 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.actions; - -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.lang.Language; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - -public class LayoutCodeSettingsStorage { - - private LayoutCodeSettingsStorage() { - } - - public static void saveRearrangeEntriesOptionFor(@NotNull Project project, @NotNull Language language, boolean value) { - String key = getRearrangeEntriesKeyForLanguage(language); - PropertiesComponent.getInstance(project).setValue(key, Boolean.toString(value)); - } - - public static void saveRearrangeEntriesOptionFor(@NotNull Project project, boolean value) { - PropertiesComponent.getInstance(project).setValue(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, Boolean.toString(value)); - } - - public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project) { - return PropertiesComponent.getInstance(project).getBoolean(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, false); - } - - public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project, @NotNull Language language) { - String key = getRearrangeEntriesKeyForLanguage(language); - return PropertiesComponent.getInstance(project).getBoolean(key, false); - } - - private static String getRearrangeEntriesKeyForLanguage(@NotNull Language language) { - return LayoutCodeConstants.REARRANGE_ENTRIES_KEY + language.getDisplayName(); - } - -} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java index 7f76f1b012a5..7690e09339f8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java @@ -47,6 +47,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi private final Project myProject; private final String myText; private final boolean myEnableOnlyVCSChangedTextCb; + private final LastRunReformatCodeOptionsProvider myLastRunOptions; private JLabel myTitle; protected JCheckBox myIncludeSubdirsCb; @@ -75,6 +76,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi myText = text; myProject = project; myEnableOnlyVCSChangedTextCb = enableOnlyVCSChangedTextCb; + myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle(title); @@ -100,11 +102,11 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi } private void restoreCbsStates() { - myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false)); - myCbRearrangeEntries.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject)); + myCbOptimizeImports.setSelected(myLastRunOptions.getLastOptimizeImports()); + myCbRearrangeEntries.setSelected(myLastRunOptions.getLastRearrangeCode()); myCbOnlyVcsChangedRegions.setEnabled(myEnableOnlyVCSChangedTextCb); myCbOnlyVcsChangedRegions.setSelected( - myEnableOnlyVCSChangedTextCb && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) + myEnableOnlyVCSChangedTextCb && myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT ); } @@ -177,7 +179,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi } @Override - public boolean isRearrangeEntries() { + public boolean isRearrangeCode() { return myCbRearrangeEntries.isSelected(); } @@ -189,10 +191,10 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi @Override protected void doOKAction() { super.doOKAction(); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports())); - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); + myLastRunOptions.saveOptimizeImportsState(isOptimizeImports()); + myLastRunOptions.saveRearrangeCodeState(isRearrangeCode()); if (myEnableOnlyVCSChangedTextCb) { - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected())); + myLastRunOptions.saveProcessVcsChangedTextState(getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT); } } @@ -200,10 +202,6 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi return myCbOptimizeImports.isSelected(); } - public boolean isProcessOnlyChangedText() { - return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected(); - } - @Nullable public String getFileTypeMask() { if (myEnableFileNameFilterCb.isSelected()) { @@ -232,4 +230,10 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi return false; } + @Override + public TextRangeType getTextRangeType() { + return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected() + ? TextRangeType.VCS_CHANGED_TEXT + : TextRangeType.WHOLE_FILE; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java index 0295fee17973..3f17fc67a5ec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java @@ -17,11 +17,11 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.LanguageImportStatements; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -72,13 +72,16 @@ public class OptimizeImportsAction extends AnAction { if (projectContext != null || moduleContext != null) { final String text; + final boolean hasChanges; if (moduleContext != null) { text = CodeInsightBundle.message("process.scope.module", moduleContext.getName()); + hasChanges = FormatChangedTextUtil.hasChanges(moduleContext); } else { text = CodeInsightBundle.message("process.scope.project", projectContext.getPresentableUrl()); + hasChanges = FormatChangedTextUtil.hasChanges(projectContext); } - DialogWrapper dialog = new OptimizeOnModuleDialog(project, text); + DialogWrapper dialog = new OptimizeImportsDialog(project, text, hasChanges); if (!dialog.showAndGet()) { return; } @@ -106,29 +109,21 @@ public class OptimizeImportsAction extends AnAction { } } - boolean processDirectory; - boolean includeSubdirectories; - - if (ApplicationManager.getApplication().isUnitTestMode()) { - includeSubdirectories = processDirectory = false; - } - else if (!EditorSettingsExternalizable.getInstance().getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG && file != null) { - includeSubdirectories = processDirectory = false; - } - else { - final LayoutCodeDialog dialog = - new LayoutCodeDialog(project, CodeInsightBundle.message("process.optimize.imports"), file, dir, null, HELP_ID); - if (!dialog.showAndGet()) { + boolean processDirectory = false; + boolean processOnlyVcsChangedFiles = false; + if (!ApplicationManager.getApplication().isUnitTestMode() && file == null && dir != null) { + String message = CodeInsightBundle.message("process.scope.directory", dir.getName()); + OptimizeImportsDialog dialog = new OptimizeImportsDialog(project, message, FormatChangedTextUtil.hasChanges(dir)); + dialog.show(); + if (!dialog.isOK()) { return; } - EditorSettingsExternalizable.getInstance().getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG = !dialog.isDoNotAskMe(); - ReformatCodeAction.updateShowDialogSetting(dialog, "\"Optimize Imports\" dialog disabled"); - processDirectory = dialog.isProcessDirectory(); - includeSubdirectories = dialog.isIncludeSubdirectories(); + processDirectory = true; + processOnlyVcsChangedFiles = dialog.isProcessOnlyVcsChangedFiles(); } if (processDirectory){ - new OptimizeImportsProcessor(project, dir, includeSubdirectories).run(); + new OptimizeImportsProcessor(project, dir, true, processOnlyVcsChangedFiles).run(); } else{ new OptimizeImportsProcessor(project, file).run(); @@ -204,21 +199,43 @@ public class OptimizeImportsAction extends AnAction { return !LanguageImportStatements.INSTANCE.forFile(file).isEmpty(); } - private static class OptimizeOnModuleDialog extends DialogWrapper { - private final String myText; + private static class OptimizeImportsDialog extends DialogWrapper { + private final boolean myContextHasChanges; - OptimizeOnModuleDialog(Project project, String text) { + private final String myText; + private JCheckBox myOnlyVcsCheckBox; + private final LastRunReformatCodeOptionsProvider myLastRunOptions; + + OptimizeImportsDialog(Project project, String text, boolean hasChanges) { super(project, false); myText = text; + myContextHasChanges = hasChanges; + myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle(CodeInsightBundle.message("process.optimize.imports")); init(); } + public boolean isProcessOnlyVcsChangedFiles() { + return myOnlyVcsCheckBox.isSelected(); + } + @Nullable @Override protected JComponent createCenterPanel() { - return new JLabel(myText); + JPanel panel = new JPanel(); + BoxLayout layout = new BoxLayout(panel, BoxLayout.Y_AXIS); + panel.setLayout(layout); + + panel.add(new JLabel(myText)); + myOnlyVcsCheckBox = new JCheckBox(CodeInsightBundle.message("process.scope.changed.files")); + boolean lastRunVcsChangedTextEnabled = myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; + + myOnlyVcsCheckBox.setEnabled(myContextHasChanges); + myOnlyVcsCheckBox.setSelected(myContextHasChanges && lastRunVcsChangedTextEnabled); + + panel.add(myOnlyVcsCheckBox); + return panel; } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index 6cdb063c0434..1428605281ff 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -25,16 +25,21 @@ import com.intellij.openapi.util.EmptyRunnable; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.FutureTask; +import static com.intellij.codeInsight.actions.OptimizeImportsProcessor.NotificationInfo.*; + public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { private static final String PROGRESS_TEXT = CodeInsightBundle.message("progress.text.optimizing.imports"); public static final String COMMAND_NAME = CodeInsightBundle.message("process.optimize.imports"); + private List myOptimizerNotifications = ContainerUtil.newSmartList(); public OptimizeImportsProcessor(Project project) { super(project, COMMAND_NAME, PROGRESS_TEXT, false); @@ -48,6 +53,10 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, false); } + public OptimizeImportsProcessor(Project project, PsiDirectory directory, boolean includeSubdirs, boolean processOnlyVcsChangedFiles) { + super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, processOnlyVcsChangedFiles); + } + public OptimizeImportsProcessor(Project project, PsiFile file) { super(project, file, PROGRESS_TEXT, COMMAND_NAME, false); } @@ -77,20 +86,79 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { } } } - Runnable runnable = runnables.isEmpty() ? EmptyRunnable.getInstance() : new Runnable() { + + Runnable runnable = !runnables.isEmpty() ? new Runnable() { @Override public void run() { CodeStyleManagerImpl.setSequentialProcessingAllowed(false); try { for (Runnable runnable : runnables) { runnable.run(); + retrieveAndStoreNotificationInfo(runnable); } + putNotificationInfoIntoCollector(); } finally { CodeStyleManagerImpl.setSequentialProcessingAllowed(true); } } - }; + } : EmptyRunnable.getInstance(); return new FutureTask(runnable, true); } + + private void retrieveAndStoreNotificationInfo(@NotNull Runnable runnable) { + if (runnable instanceof ImportOptimizer.CollectingInfoRunnable) { + String optimizerMessage = ((ImportOptimizer.CollectingInfoRunnable)runnable).getUserNotificationInfo(); + myOptimizerNotifications.add(optimizerMessage != null ? new NotificationInfo(optimizerMessage) : NOTHING_CHANGED_NOTIFICATION); + } + else if (runnable == EmptyRunnable.getInstance()) { + myOptimizerNotifications.add(NOTHING_CHANGED_NOTIFICATION); + } + else { + myOptimizerNotifications.add(SOMETHING_CHANGED_WITHOUT_MESSAGE_NOTIFICATION); + } + } + + private void putNotificationInfoIntoCollector() { + LayoutCodeInfoCollector collector = getInfoCollector(); + if (collector == null) { + return; + } + + boolean atLeastOneOptimizerChangedSomething = false; + for (NotificationInfo info : myOptimizerNotifications) { + atLeastOneOptimizerChangedSomething |= info.isSomethingChanged(); + if (info.getMessage() != null) { + collector.setOptimizeImportsNotification(info.getMessage()); + return; + } + } + + collector.setOptimizeImportsNotification(atLeastOneOptimizerChangedSomething ? "imports optimized" : null); + } + + static class NotificationInfo { + public static final NotificationInfo NOTHING_CHANGED_NOTIFICATION = new NotificationInfo(false, null); + public static final NotificationInfo SOMETHING_CHANGED_WITHOUT_MESSAGE_NOTIFICATION = new NotificationInfo(true, null); + + private final boolean mySomethingChanged; + private final String myMessage; + + NotificationInfo(@NotNull String message) { + this(true, message); + } + + public boolean isSomethingChanged() { + return mySomethingChanged; + } + + public String getMessage() { + return myMessage; + } + + private NotificationInfo(boolean isSomethingChanged, @Nullable String message) { + mySomethingChanged = isSomethingChanged; + myMessage = message; + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeConstants.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptionalReformatActions.java similarity index 54% rename from platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeConstants.java rename to platform/lang-impl/src/com/intellij/codeInsight/actions/OptionalReformatActions.java index 84de47d7f457..e71f5c116ad5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeConstants.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptionalReformatActions.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,18 +15,10 @@ */ package com.intellij.codeInsight.actions; -import org.jetbrains.annotations.NonNls; +public interface OptionalReformatActions { -/** - * @author Denis Zhdanov - * @since 12/16/11 6:10 PM - */ -public class LayoutCodeConstants { + boolean isOptimizeImports(); - @NonNls public static final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports"; - @NonNls public static final String REARRANGE_ENTRIES_KEY = "LayoutCode.rearrangeEntries"; - @NonNls public static final String PROCESS_CHANGED_TEXT_KEY = "LayoutCode.processChangedText"; + boolean isRearrangeCode(); - private LayoutCodeConstants() { - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index 4867d85abbd7..fc264cdb61cc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -15,8 +15,10 @@ */ package com.intellij.codeInsight.actions; +import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; @@ -25,21 +27,22 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.arrangement.Rearranger; import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine; -import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; -import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { public static final String COMMAND_NAME = "Rearrange code"; - public static final String PROGRESS_TEXT = "Rearranging code..."; + public static final String PROGRESS_TEXT = CodeInsightBundle.message("process.rearrange.code"); - @Nullable private SelectionModel mySelectionModel; + private static final Logger LOG = Logger.getInstance(RearrangeCodeProcessor.class); + private SelectionModel mySelectionModel; public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor) { super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); @@ -49,14 +52,16 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); mySelectionModel = selectionModel; } - - public RearrangeCodeProcessor(@NotNull Project project, - @NotNull PsiFile file, - @Nullable SelectionModel selectionModel) { - super(project, file, PROGRESS_TEXT, COMMAND_NAME, false); + + public RearrangeCodeProcessor(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false); mySelectionModel = selectionModel; } + public RearrangeCodeProcessor(@NotNull PsiFile file) { + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false); + } + public RearrangeCodeProcessor(@NotNull Project project, @NotNull PsiFile[] files, @NotNull String commandName, @@ -70,70 +75,55 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { return new FutureTask(new Callable() { @Override public Boolean call() throws Exception { - Collection ranges = processChangedTextOnly ? FormatChangedTextUtil.getChangedTextRanges(myProject, file) - : getRangesToFormat(file); + try { + Collection ranges = getRangesToFormat(file, processChangedTextOnly); + Document document = PsiDocumentManager.getInstance(myProject).getDocument(file); - RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME, ranges); - if (rearranger.couldRearrange()) { - rearranger.run(); + if (document != null && Rearranger.EXTENSION.forLanguage(file.getLanguage()) != null) { + Runnable command = prepareRearrangeCommand(file, ranges); + PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(document); + try { + CommandProcessor.getInstance().executeCommand(myProject, command, COMMAND_NAME, null); + } + finally { + PsiDocumentManager.getInstance(myProject).commitDocument(document); + } + } + + return true; + } + catch (FilesTooBigForDiffException e) { + handleFileTooBigException(LOG, e, file); + return false; } - return true; } }); } - public Collection getRangesToFormat(@NotNull PsiFile file) { - final List ranges = new SmartList(); - if (mySelectionModel != null && mySelectionModel.hasSelection()) { - ranges.add(TextRange.create(mySelectionModel.getSelectionStart(), mySelectionModel.getSelectionEnd())); - } - else { - ranges.add(TextRange.create(0, file.getTextLength())); - } - return ranges; - } -} - - -class RearrangeCommand { - @NotNull private PsiFile myFile; - @NotNull private String myCommandName; - @NotNull private Project myProject; - private Document myDocument; - private Runnable myCommand; - private final Collection myRanges; - - RearrangeCommand(@NotNull Project project, @NotNull PsiFile file, @NotNull String commandName, @NotNull Collection ranges) { - myProject = project; - myFile = file; - myRanges = ranges; - myCommandName = commandName; - myDocument = PsiDocumentManager.getInstance(project).getDocument(file); - } - - boolean couldRearrange() { - return myDocument != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; - } - - void run() { - assert myDocument != null; - prepare(); - try { - CommandProcessor.getInstance().executeCommand(myProject, myCommand, myCommandName, null); - } - finally { - PsiDocumentManager.getInstance(myProject).commitDocument(myDocument); - } - } - - private void prepare() { + @NotNull + private Runnable prepareRearrangeCommand(@NotNull final PsiFile file, @NotNull final Collection ranges) { final ArrangementEngine engine = ServiceManager.getService(myProject, ArrangementEngine.class); - myCommand = new Runnable() { + return new Runnable() { @Override public void run() { - engine.arrange(myFile, myRanges); + engine.arrange(file, ranges); + if (getInfoCollector() != null) { + String info = engine.getUserNotificationInfo(); + getInfoCollector().setRearrangeCodeNotification(info); + } } }; - PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myDocument); + } + + public Collection getRangesToFormat(@NotNull PsiFile file, boolean processChangedTextOnly) throws FilesTooBigForDiffException { + if (mySelectionModel != null) { + return getSelectedRanges(mySelectionModel); + } + + if (processChangedTextOnly) { + return FormatChangedTextUtil.getChangedTextRanges(myProject, file); + } + + return ContainerUtil.newSmartList(file.getTextRange()); } } 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 ba3d2d961f00..bdff57d94240 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -16,32 +16,22 @@ package com.intellij.codeInsight.actions; -import com.intellij.application.options.editor.EditorOptions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.find.impl.FindInProjectUtil; import com.intellij.formatting.FormattingModelBuilder; import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.LanguageFormatting; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationListener; -import com.intellij.notification.NotificationType; -import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.module.Module; -import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.LocalSearchScope; @@ -53,8 +43,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import javax.swing.*; -import javax.swing.event.HyperlinkEvent; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -95,14 +83,14 @@ public class ReformatCodeAction extends AnAction implements DumbAware { if (selectedFlags == null) return; - final boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText(); + final boolean processOnlyChangedText = selectedFlags.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; final boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb(); AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor(project, convertToPsiFiles(files, project), null, processOnlyChangedText); if (shouldOptimizeImports) { processor = new OptimizeImportsProcessor(processor); } - if (selectedFlags.isRearrangeEntries()) { + if (selectedFlags.isRearrangeCode()) { processor = new RearrangeCodeProcessor(processor); } @@ -134,15 +122,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } } - boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn(); - boolean processWholeFile = false; - boolean processChangedTextOnly = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); - boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file); - - final boolean showDialog = EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG; - - if (file == null && dir == null) return; - if (file == null) { + if (file == null && dir != null) { DirectoryFormattingOptions options = getDirectoryFormattingOptions(project, dir); if (options != null) { reformatDirectory(project, dir, options); @@ -150,57 +130,29 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return; } - if (showDialog) { - LayoutCodeOptions selectedFlags = getLayoutCodeOptions(project, file, dir, hasSelection); - if (selectedFlags == null) - return; + if (file == null || editor == null) return; - optimizeImports = selectedFlags.isOptimizeImports(); - rearrangeEntries = selectedFlags.isRearrangeEntries(); - processWholeFile = selectedFlags.isProcessWholeFile(); - processChangedTextOnly = selectedFlags.isProcessOnlyChangedText(); + LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + ReformatCodeRunOptions currentRunOptions = provider.getLastRunOptions(file); - if (selectedFlags.isProcessDirectory()) { - assert dir != null : "File = " + file + ", Element = " + CommonDataKeys.PSI_ELEMENT.getData(dataContext); - reformatDirectory(project, dir, selectedFlags); - return; + TextRangeType processingScope = currentRunOptions.getTextRangeType(); + if (hasSelection) { + processingScope = TextRangeType.SELECTED_TEXT; + } + else if (processingScope == TextRangeType.VCS_CHANGED_TEXT) { + if (isChangeNotTrackedForFile(project, file)) { + processingScope = TextRangeType.WHOLE_FILE; } } - - if (!showDialog && processChangedTextOnly && isChangeNotTrackedForFile(project, file)) { - processChangedTextOnly = false; - } - - final TextRange range; - final boolean processSelectedText = !processWholeFile && hasSelection; - if (processSelectedText) { - range = TextRange.create(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd()); - } - else{ - range = null; - } - - AbstractLayoutCodeProcessor processor; - if (optimizeImports && range == null) { - processor = new OptimizeImportsProcessor(project, file); - processor = new ReformatCodeProcessor(processor, processChangedTextOnly); - } else { - processor = new ReformatCodeProcessor(project, file, range, !processSelectedText && processChangedTextOnly); + processingScope = TextRangeType.WHOLE_FILE; } - if (rearrangeEntries) { - if (processSelectedText && editor != null) { - processor = new RearrangeCodeProcessor(processor, editor.getSelectionModel()); - } - else { - processor = new RearrangeCodeProcessor(processor); - } - } - - processor.run(); + currentRunOptions.setProcessingScope(processingScope); + new FileInEditorProcessor(file, editor, currentRunOptions).processCode(); } + private static boolean isChangeNotTrackedForFile(@NotNull Project project, @NotNull PsiFile file) { boolean isUnderVcs = VcsUtil.isFileUnderVcs(project, VcsUtil.getFilePath(file.getVirtualFile())); if (!isUnderVcs) return true; @@ -238,10 +190,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { @NotNull DirectoryFormattingOptions options) { AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor( - project, - dir, - options.isIncludeSubdirectories(), - options.isProcessOnlyChangedText() + project, dir, options.isIncludeSubdirectories(), options.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT ); registerScopeFilter(processor, options.getSearchScope()); @@ -250,7 +199,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { if (options.isOptimizeImports()) { processor = new OptimizeImportsProcessor(processor); } - if (options.isRearrangeEntries()) { + if (options.isRearrangeCode()) { processor = new RearrangeCodeProcessor(processor); } @@ -262,7 +211,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { @NotNull ReformatFilesOptions selectedFlags) { boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb(); - boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText(); + boolean processOnlyChangedText = selectedFlags.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; AbstractLayoutCodeProcessor processor; if (moduleContext != null) @@ -277,7 +226,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { processor = new OptimizeImportsProcessor(processor); } - if (selectedFlags.isRearrangeEntries()) { + if (selectedFlags.isRearrangeCode()) { processor = new RearrangeCodeProcessor(processor); } @@ -329,23 +278,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } } - public static void updateShowDialogSetting(LayoutCodeDialog dialog, String title) { - if (dialog.isDoNotAskMe()) { - Notifications.Bus.notify(new Notification("Reformat Code", title, - "You can re-enable the dialog on the IDE Settings -> Editor pane", - NotificationType.INFORMATION, new NotificationListener() { - @Override - public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - final ShowSettingsUtil util = ShowSettingsUtil.getInstance(); - IdeFrame ideFrame = WindowManagerEx.getInstanceEx().findFrameFor(null); - util.editConfigurable((JFrame)ideFrame, new EditorOptions()); - } - } - })); - } - } - public static PsiFile[] convertToPsiFiles(final VirtualFile[] files,Project project) { final PsiManager manager = PsiManager.getInstance(project); final ArrayList result = new ArrayList(); @@ -457,31 +389,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return dialog; } - @Nullable - private static LayoutCodeOptions getLayoutCodeOptions(@NotNull Project project, - @Nullable PsiFile file, - @Nullable PsiDirectory dir, - boolean hasSelection) { - if (ApplicationManager.getApplication().isUnitTestMode()) { - return (LayoutCodeOptions)myTestOptions; - } - LayoutCodeDialog dialog = new LayoutCodeDialog(project, CodeInsightBundle.message("process.reformat.code"), - file, dir, hasSelection ? Boolean.TRUE : Boolean.FALSE, HELP_ID); - if (!dialog.showAndGet()) { - return null; - } - EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG = !dialog.isDoNotAskMe(); - updateShowDialogSetting(dialog, "\"Reformat Code\" dialog disabled"); - return dialog; - } - - public static boolean getLastSavedRearrangeCbState(@NotNull Project project, @Nullable PsiFile file) { - if (file != null) { - return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project, file.getLanguage()); - } - return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project); - } - @TestOnly protected static void setTestOptions(ReformatFilesOptions options) { myTestOptions = options; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 4ebe9274c1ca..e9f80bd23fad 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -18,15 +18,14 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.formatting.FormattingProgressTask; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationType; -import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.util.IncorrectOperationException; @@ -46,13 +45,24 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.ReformatCodeProcessor"); - private final Collection myRanges = new ArrayList(); private static final String PROGRESS_TEXT = CodeInsightBundle.message("reformat.progress.common.text"); + private final Collection myRanges = new ArrayList(); + private SelectionModel mySelectionModel; public ReformatCodeProcessor(Project project, boolean processChangedTextOnly) { super(project, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly); } + public ReformatCodeProcessor(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { + super(file.getProject(), file, COMMAND_NAME, PROGRESS_TEXT, false); + mySelectionModel = selectionModel; + } + + public ReformatCodeProcessor(AbstractLayoutCodeProcessor processor, @NotNull SelectionModel selectionModel) { + super(processor, COMMAND_NAME, PROGRESS_TEXT); + mySelectionModel = selectionModel; + } + public ReformatCodeProcessor(AbstractLayoutCodeProcessor processor, boolean processChangedTextOnly) { super(processor, COMMAND_NAME, PROGRESS_TEXT); setProcessChangedTextOnly(processChangedTextOnly); @@ -73,6 +83,10 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } } + public ReformatCodeProcessor(@NotNull PsiFile file, boolean processChangedTextOnly) { + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly); + } + public ReformatCodeProcessor(Project project, PsiFile[] files, @Nullable Runnable postRunnable, boolean processChangedTextOnly) { this(project, files, COMMAND_NAME, postRunnable, processChangedTextOnly); } @@ -92,23 +106,31 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { throws IncorrectOperationException { return new FutureTask(new Callable() { + private Document myDocument; + @Override public Boolean call() throws Exception { FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false); try { Collection ranges = getRangesToFormat(processChangedTextOnly, file); + + CharSequence before = null; + if (getInfoCollector() != null) { + myDocument = PsiDocumentManager.getInstance(myProject).getDocument(file); + LOG.assertTrue(myDocument != null); + before = myDocument.getImmutableCharSequence(); + } + CodeStyleManager.getInstance(myProject).reformatText(file, ranges); + + if (before != null) { + prepareUserNotificationMessage(myDocument, before); + } + return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get(); } catch (FilesTooBigForDiffException e) { - LOG.info("Error while calculating changed ranges for: " + file.getVirtualFile(), e); - if (!ApplicationManager.getApplication().isUnitTestMode()) { - Notification notification = new Notification(ApplicationBundle.message("reformat.changed.text.file.too.big.notification.groupId"), - ApplicationBundle.message("reformat.changed.text.file.too.big.notification.title"), - ApplicationBundle.message("reformat.changed.text.file.too.big.notification.text", file.getName()), - NotificationType.INFORMATION); - notification.notify(file.getProject()); - } + handleFileTooBigException(LOG, e, file); return false; } catch (IncorrectOperationException e) { @@ -122,8 +144,21 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { }); } + private void prepareUserNotificationMessage(@NotNull Document document, @NotNull CharSequence before) { + LOG.assertTrue(getInfoCollector() != null); + int number = FormatChangedTextUtil.calculateChangedLinesNumber(document, before); + if (number > 0) { + String message = "formatted " + number + " line" + (number > 1 ? "s" : ""); + getInfoCollector().setReformatCodeNotification(message); + } + } + @NotNull private Collection getRangesToFormat(boolean processChangedTextOnly, PsiFile file) throws FilesTooBigForDiffException { + if (mySelectionModel != null) { + return getSelectedRanges(mySelectionModel); + } + if (processChangedTextOnly) { return FormatChangedTextUtil.getChangedTextRanges(myProject, file); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java new file mode 100644 index 000000000000..67d20e28b735 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.actions; + +public class ReformatCodeRunOptions implements LayoutCodeOptions { + + private boolean myRearrangeCode; + private boolean myOptimizeImports; + private TextRangeType myProcessingScope; + + public ReformatCodeRunOptions(TextRangeType processingScope) { + myProcessingScope = processingScope; + } + + public void setProcessingScope(TextRangeType processingScope) { + myProcessingScope = processingScope; + } + + @Override + public boolean isOptimizeImports() { + return myOptimizeImports; + } + + @Override + public boolean isRearrangeCode() { + return myRearrangeCode; + } + + public ReformatCodeRunOptions setRearrangeCode(boolean rearrangeCode) { + myRearrangeCode = rearrangeCode; + return this; + } + + public ReformatCodeRunOptions setOptimizeImports(boolean optimizeImports) { + myOptimizeImports = optimizeImports; + return this; + } + + @Override + public TextRangeType getTextRangeType() { + return myProcessingScope; + } + +} + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java index d364857352e6..a7651cd34cb5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java @@ -27,25 +27,27 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; +import static com.intellij.codeInsight.actions.TextRangeType.*; + public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesOptions { - @NotNull private Project myProject; private JPanel myPanel; private JCheckBox myOptimizeImports; private JCheckBox myOnlyChangedText; private JCheckBox myRearrangeEntriesCb; + private final LastRunReformatCodeOptionsProvider myLastRunSettings; + public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) { super(project, true); - myProject = project; - setTitle(CodeInsightBundle.message("dialog.reformat.files.title")); - myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); + myLastRunSettings = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + boolean canTargetVcsChanges = FormatChangedTextUtil.hasChanges(files, project); myOnlyChangedText.setEnabled(canTargetVcsChanges); - myOnlyChangedText.setSelected( - canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) - ); - myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); - myRearrangeEntriesCb.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject)); + myOnlyChangedText.setSelected(canTargetVcsChanges && myLastRunSettings.getLastTextRangeType() == VCS_CHANGED_TEXT); + myOptimizeImports.setSelected(myLastRunSettings.getLastOptimizeImports()); + myRearrangeEntriesCb.setSelected(myLastRunSettings.getLastRearrangeCode()); + + setTitle(CodeInsightBundle.message("dialog.reformat.files.title")); init(); } @@ -60,25 +62,25 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO } @Override - public boolean isProcessOnlyChangedText() { - return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected(); + public TextRangeType getTextRangeType() { + return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected() + ? VCS_CHANGED_TEXT + : WHOLE_FILE; } @Override - public boolean isRearrangeEntries() { + public boolean isRearrangeCode() { return myRearrangeEntriesCb.isSelected(); } @Override protected void doOKAction() { super.doOKAction(); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected())); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected())); - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); - } - - static boolean isOptmizeImportsOptionOn() { - return PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false); + myLastRunSettings.saveOptimizeImportsState(isOptimizeImports()); + myLastRunSettings.saveRearrangeCodeState(isRearrangeCode()); + if (myOnlyChangedText.isEnabled()) { + myLastRunSettings.saveProcessVcsChangedTextState(getTextRangeType() == VCS_CHANGED_TEXT); + } } @Nullable diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java index bb958e77b2fe..f10757940324 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java @@ -18,13 +18,7 @@ package com.intellij.codeInsight.actions; import com.intellij.psi.search.SearchScope; import org.jetbrains.annotations.Nullable; -public interface ReformatFilesOptions { - - boolean isOptimizeImports(); - - boolean isProcessOnlyChangedText(); - - boolean isRearrangeEntries(); +public interface ReformatFilesOptions extends LayoutCodeOptions { @Nullable String getFileTypeMask(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ShowReformatFileDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ShowReformatFileDialog.java new file mode 100644 index 000000000000..b564b939ea1e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ShowReformatFileDialog.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.actions; + +import com.intellij.lang.LanguageFormatting; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NonNls; + +public class ShowReformatFileDialog extends AnAction implements DumbAware { + private static final @NonNls String HELP_ID = "editing.codeReformatting"; + + @Override + public void update(AnActionEvent event) { + Presentation presentation = event.getPresentation(); + DataContext dataContext = event.getDataContext(); + Project project = CommonDataKeys.PROJECT.getData(dataContext); + Editor editor = CommonDataKeys.EDITOR.getData(dataContext); + if (project == null || editor == null) { + presentation.setEnabled(false); + return; + } + + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (file == null || file.getVirtualFile() == null) { + presentation.setEnabled(false); + return; + } + + if (LanguageFormatting.INSTANCE.forContext(file) != null) { + presentation.setEnabled(true); + } + } + + @Override + public void actionPerformed(AnActionEvent event) { + Presentation presentation = event.getPresentation(); + DataContext dataContext = event.getDataContext(); + Project project = CommonDataKeys.PROJECT.getData(dataContext); + Editor editor = CommonDataKeys.EDITOR.getData(dataContext); + if (project == null || editor == null) { + presentation.setEnabled(false); + return; + } + + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (file == null || file.getVirtualFile() == null) { + presentation.setEnabled(false); + return; + } + + boolean hasSelection = editor.getSelectionModel().hasSelection(); + LayoutCodeDialog dialog = new LayoutCodeDialog(project, file, hasSelection, HELP_ID); + dialog.show(); + + if (dialog.isOK()) { + new FileInEditorProcessor(file, editor, dialog.getRunOptions()).processCode(); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java index d4889a97f802..0334f18b0931 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -24,13 +24,13 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProfileManagerImpl; -import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; +import com.intellij.util.xmlb.SkipDefaultsSerializationFilter; import com.intellij.util.xmlb.XmlSerializer; import org.jdom.Element; @State( name = "DaemonCodeAnalyzerSettings", - storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/editor.codeinsight.xml")} + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/editor.codeinsight.xml") ) public class DaemonCodeAnalyzerSettingsImpl extends DaemonCodeAnalyzerSettings implements PersistentStateComponent, Cloneable { @Override @@ -42,7 +42,7 @@ public class DaemonCodeAnalyzerSettingsImpl extends DaemonCodeAnalyzerSettings i public DaemonCodeAnalyzerSettingsImpl clone() { DaemonCodeAnalyzerSettingsImpl settings = new DaemonCodeAnalyzerSettingsImpl(); settings.AUTOREPARSE_DELAY = AUTOREPARSE_DELAY; - settings.SHOW_ADD_IMPORT_HINTS = SHOW_ADD_IMPORT_HINTS; + settings.myShowAddImportHints = myShowAddImportHints; settings.SHOW_METHOD_SEPARATORS = SHOW_METHOD_SEPARATORS; settings.NO_AUTO_IMPORT_PATTERN = NO_AUTO_IMPORT_PATTERN; settings.SHOW_SMALL_ICONS_IN_GUTTER = SHOW_SMALL_ICONS_IN_GUTTER; @@ -51,7 +51,7 @@ public class DaemonCodeAnalyzerSettingsImpl extends DaemonCodeAnalyzerSettings i @Override public Element getState() { - Element element = XmlSerializer.serialize(this, new SkipDefaultValuesSerializationFilters()); + Element element = XmlSerializer.serialize(this, new SkipDefaultsSerializationFilter()); String profile = InspectionProfileManager.getInstance().getRootProfile().getName(); if (!"Default".equals(profile)) { element.setAttribute("profile", profile); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java index b6f951efb865..449f0865f793 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java @@ -356,7 +356,7 @@ public class EnterHandler extends BaseEnterHandler { commentContext.docStart = false; } else { - commentContext.docAsterisk = true; + commentContext.docAsterisk = CodeStyleSettingsManager.getSettings(getProject()).JD_LEADING_ASTERISKS_ARE_ENABLED; commentContext.docStart = false; } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java index c7c05dc68d74..3f644c04fd39 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java @@ -452,12 +452,10 @@ public class TemplateSettings implements PersistentStateComponent", "'"); + descriptionTemplate = StringUtil.replace(descriptionTemplate, "", "'"); descriptionTemplate = XmlStringUtil.escapeString(descriptionTemplate); } //noinspection HardCodedStringLiteral diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java index 1aa103dfa6b1..f1cf7487bde4 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java @@ -17,7 +17,6 @@ package com.intellij.execution.console; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupManager; -import com.intellij.execution.process.ConsoleHistoryModel; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -108,7 +107,6 @@ public class ConsoleExecuteAction extends DumbAwareAction { } public static abstract class ConsoleExecuteActionHandler { - private ConsoleHistoryModel myCommandHistoryModel; private boolean myAddToHistory = true; final boolean myPreserveMarkup; @@ -119,18 +117,6 @@ public class ConsoleExecuteAction extends DumbAwareAction { myPreserveMarkup = preserveMarkup; } - @NotNull - public ConsoleHistoryModel getConsoleHistoryModel() { - if (myCommandHistoryModel == null) { - myCommandHistoryModel = new ConsoleHistoryModel(); - } - return myCommandHistoryModel; - } - - void setConsoleHistoryModel(@NotNull ConsoleHistoryModel model) { - myCommandHistoryModel = model; - } - public boolean isEmptyCommandExecutionAllowed() { return true; } @@ -162,7 +148,7 @@ public class ConsoleExecuteAction extends DumbAwareAction { } private void addToCommandHistoryAndExecute(@NotNull LanguageConsoleView consoleView, @NotNull String text) { - getConsoleHistoryModel().addToHistory(text); + ConsoleHistoryController.addToHistory(consoleView, text); doExecute(text, consoleView); } diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java index e4bdbdca11a2..155158367d7e 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java @@ -16,7 +16,6 @@ package com.intellij.execution.console; import com.intellij.codeInsight.lookup.LookupManager; -import com.intellij.execution.process.ConsoleHistoryModel; import com.intellij.ide.scratch.ScratchFileService; import com.intellij.lang.Language; import com.intellij.openapi.Disposable; @@ -40,6 +39,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringHash; import com.intellij.openapi.util.text.StringUtil; @@ -75,8 +75,11 @@ import java.util.*; */ public class ConsoleHistoryController { + private static final Key CONTROLLER_KEY = Key.create("CONTROLLER_KEY"); + private static final Logger LOG = Logger.getInstance("com.intellij.execution.console.ConsoleHistoryController"); + /** @noinspection MismatchedQueryAndUpdateOfCollection*/ private final static FactoryMap ourModels = new FactoryMap() { @Override protected Map createMap() { @@ -86,7 +89,7 @@ public class ConsoleHistoryController { @Nullable @Override protected ConsoleHistoryModel create(String key) { - return new ConsoleHistoryModel(); + return new ConsoleHistoryModel(null); } }; @@ -99,9 +102,8 @@ public class ConsoleHistoryController { private long myLastSaveStamp; @Deprecated - public ConsoleHistoryController(@NotNull String type, @Nullable String persistenceId, - @NotNull LanguageConsoleView console, @NotNull ConsoleHistoryModel model) { - this(new ConsoleRootType(type, null) { }, persistenceId, console, model); + public ConsoleHistoryController(@NotNull String type, @Nullable String persistenceId, @NotNull LanguageConsoleView console) { + this(new ConsoleRootType(type, null) { }, persistenceId, console); } public ConsoleHistoryController(@NotNull ConsoleRootType rootType, @Nullable String persistenceId, @NotNull LanguageConsoleView console) { @@ -110,8 +112,28 @@ public class ConsoleHistoryController { private ConsoleHistoryController(@NotNull ConsoleRootType rootType, @Nullable String persistenceId, @NotNull LanguageConsoleView console, @NotNull ConsoleHistoryModel model) { - myHelper = new ModelHelper(rootType, fixNullPersistenceId(persistenceId, console), model); + myHelper = new ModelHelper(rootType, fixNullPersistenceId(persistenceId, console), model.copy()); myConsole = console; + console.getVirtualFile().putUserData(CONTROLLER_KEY, this); + } + + public static ConsoleHistoryController getController(LanguageConsoleView console) { + return console.getVirtualFile().getUserData(CONTROLLER_KEY); + } + + public static void addToHistory(@NotNull LanguageConsoleView consoleView, @Nullable String command) { + ConsoleHistoryController controller = getController(consoleView); + if (controller != null) { + controller.addToHistory(command); + } + } + + public void addToHistory(@Nullable String command) { + getModel().addToHistory(command); + } + + public boolean hasHistory() { + return getModel().getHistory().isEmpty(); } private static String fixNullPersistenceId(@Nullable String persistenceId, @NotNull LanguageConsoleView console) { @@ -127,26 +149,29 @@ public class ConsoleHistoryController { return this; } - public ConsoleHistoryModel getModel() { + ConsoleHistoryModel getModel() { return myHelper.getModel(); } public void install() { + FileDocumentManager.getInstance().saveAllDocuments(); if (myHelper.getId() != null) { ApplicationManager.getApplication().getMessageBus().connect(myConsole).subscribe( ProjectEx.ProjectSaved.TOPIC, new ProjectEx.ProjectSaved() { - @Override - public void saved(@NotNull final Project project) { - saveHistory(); - } - }); + @Override + public void saved(@NotNull final Project project) { + saveHistory(); + } + }); Disposer.register(myConsole, new Disposable() { @Override public void dispose() { saveHistory(); } }); - loadHistory(myHelper.getId()); + if (myHelper.getModel().getHistorySize() == 0) { + loadHistory(myHelper.getId()); + } } configureActions(); myLastSaveStamp = getCurrentTimeStamp(); @@ -483,14 +508,15 @@ public class ConsoleHistoryController { OutputStream os = null; try { - final XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer(); + os = new SafeFileOutputStream(file); + XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer(); try { serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " "); } catch (Exception ignored) { // not recognized } - serializer.setOutput(os = new SafeFileOutputStream(file), CharsetToolkit.UTF8); + serializer.setOutput(os, CharsetToolkit.UTF8); saveHistory(serializer); serializer.flush(); } @@ -499,7 +525,9 @@ public class ConsoleHistoryController { } finally { try { - os.close(); + if (os != null) { + os.close(); + } } catch (Exception ignored) { // nothing @@ -517,7 +545,7 @@ public class ConsoleHistoryController { AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { VirtualFile file = HistoryRootType.getInstance().findFile(null, getHistoryName(myRootType, myId), ScratchFileService.Option.create_if_missing); - VfsUtil.saveText(file, StringUtil.join(ContainerUtil.reverse(getModel().getHistory()), myRootType.getEntrySeparator())); + VfsUtil.saveText(file, StringUtil.join(getModel().getHistory(), myRootType.getEntrySeparator())); } finally { token.finish(); diff --git a/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryModel.java similarity index 82% rename from platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java rename to platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryModel.java index 0e597c5089ce..415d0acd47e0 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryModel.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.execution.process; +package com.intellij.execution.console; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.util.SimpleModificationTracker; @@ -27,11 +27,22 @@ import java.util.List; /** * @author Gregory.Shrago */ -public class ConsoleHistoryModel extends SimpleModificationTracker { +class ConsoleHistoryModel extends SimpleModificationTracker { + /** @noinspection FieldCanBeLocal*/ + private final ConsoleHistoryModel myMasterModel; // hard ref private int myHistoryCursor = -1; - private final LinkedList myHistory = new LinkedList(); + private final LinkedList myHistory; - public void addToHistory(String statement) { + ConsoleHistoryModel(ConsoleHistoryModel masterModel) { + myMasterModel = masterModel; + myHistory = myMasterModel == null ? new LinkedList() : myMasterModel.myHistory; + } + + ConsoleHistoryModel copy() { + return new ConsoleHistoryModel(this); + } + + public void addToHistory(@Nullable String statement) { if (StringUtil.isEmptyOrSpaces(statement)) return; int maxHistorySize = getMaxHistorySize(); diff --git a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java index 3c7ab3eedeff..68a4f836d0fb 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java +++ b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java @@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.Disposer; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -199,14 +200,14 @@ public class DuplexConsoleView ext List actions = Lists.newArrayList(); actions.addAll(Arrays.asList(myPrimaryConsoleView.createConsoleActions())); actions.add(mySwitchConsoleAction); - addExtraActions(actions); + + LanguageConsoleView langConsole = ContainerUtil.findInstance(Arrays.asList(myPrimaryConsoleView, mySecondaryConsoleView), LanguageConsoleView.class); + ConsoleHistoryController controller = langConsole != null ? ConsoleHistoryController.getController(langConsole) : null; + if (controller != null) actions.add(controller.getBrowseHistory()); return ArrayUtil.toObjectArray(actions, AnAction.class); } - protected void addExtraActions(List actions) { - } - @Override public void allowHeavyFilters() { myPrimaryConsoleView.allowHeavyFilters(); @@ -267,7 +268,7 @@ public class DuplexConsoleView ext } @Override - public void update(final AnActionEvent event) { + public void update(@NotNull AnActionEvent event) { super.update(event); final Presentation presentation = event.getPresentation(); final boolean isRunning = myProcessHandler != null && !myProcessHandler.isProcessTerminated(); diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java index e55acb4148be..fca776ec2e66 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java @@ -27,7 +27,6 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Conditions; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; @@ -110,17 +109,17 @@ public final class LanguageConsoleBuilder { private void doInitAction(@NotNull LanguageConsoleView console, @NotNull BaseConsoleExecuteActionHandler executeActionHandler, @NotNull String historyType) { ConsoleExecuteAction action = new ConsoleExecuteAction(console, executeActionHandler, executionEnabled); action.registerCustomShortcutSet(action.getShortcutSet(), console.getConsoleEditor().getComponent()); - setupHistoryController(console, historyType, null, executeActionHandler); + new ConsoleHistoryController(historyType, null, console).install(); } /** * todo This API doesn't look good, but it is much better than force client to know low-level details */ - public static Pair registerExecuteAction(@NotNull LanguageConsoleView console, - @NotNull final Consumer executeActionHandler, - @NotNull String historyType, - @Nullable String historyPersistenceId, - @Nullable Condition enabledCondition) { + public static AnAction registerExecuteAction(@NotNull LanguageConsoleView console, + @NotNull final Consumer executeActionHandler, + @NotNull String historyType, + @Nullable String historyPersistenceId, + @Nullable Condition enabledCondition) { ConsoleExecuteAction.ConsoleExecuteActionHandler handler = new ConsoleExecuteAction.ConsoleExecuteActionHandler(true) { @Override void doExecute(@NotNull String text, @NotNull LanguageConsoleView consoleView) { @@ -130,19 +129,8 @@ public final class LanguageConsoleBuilder { ConsoleExecuteAction action = new ConsoleExecuteAction(console, handler, enabledCondition); action.registerCustomShortcutSet(action.getShortcutSet(), console.getConsoleEditor().getComponent()); - - return new Pair(action, setupHistoryController(console, historyType, historyPersistenceId, handler)); - } - - @NotNull - private static ConsoleHistoryController setupHistoryController(@NotNull LanguageConsoleView console, - @NotNull String historyType, - @Nullable String historyPersistenceId, - @NotNull ConsoleExecuteAction.ConsoleExecuteActionHandler handler) { - ConsoleHistoryController historyController = new ConsoleHistoryController(new ConsoleRootType(historyType, null) {}, historyPersistenceId, console); - historyController.install(); - handler.setConsoleHistoryModel(historyController.getModel()); - return historyController; + new ConsoleHistoryController(historyType, historyPersistenceId, console).install(); + return action; } public LanguageConsoleBuilder gutterContentProvider(@Nullable GutterContentProvider value) { diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 52765bb5a990..60b7a652617a 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -166,7 +166,7 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons return getConsoleEditor().getContentComponent(); } - public void initComponents() { + private void initComponents() { setupComponents(); myPanel.add(myHistoryViewer.getComponent()); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index 769cd314585d..e5007e50ed90 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -49,6 +49,7 @@ import java.util.*; @State( name = "RunManager", + defaultStateAsResource = true, storages = @Storage(file = StoragePathMacros.WORKSPACE_FILE) ) public class RunManagerImpl extends RunManagerEx implements PersistentStateComponent, NamedComponent, Disposable { diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java index 8bbbe7cfbe95..e9009e3300fa 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java @@ -131,7 +131,7 @@ public abstract class AbstractConsoleRunnerWithHistory() { @Override public JComponent compute() { - return getLanguageConsole().getConsoleEditor().getContentComponent(); + return getConsoleView().getConsoleEditor().getContentComponent(); } }); contentDescriptor.setAutoFocusContent(isAutoFocusContent()); @@ -139,7 +139,7 @@ public abstract class AbstractConsoleRunnerWithHistory actions = fillToolBarActions(toolbarActions, defaultExecutor, contentDescriptor); - registerActionShortcuts(actions, getLanguageConsole().getConsoleEditor().getComponent()); + registerActionShortcuts(actions, getConsoleView().getConsoleEditor().getComponent()); registerActionShortcuts(actions, panel); showConsole(defaultExecutor, contentDescriptor); @@ -234,10 +234,6 @@ public abstract class AbstractConsoleRunnerWithHistory collectFilesInScope(@NotNull final Set alreadySearched, final boolean skipIndexed) { - SearchScope customScope = myFindModel.getCustomScope(); + SearchScope customScope = myFindModel.isCustomScope() ? myFindModel.getCustomScope() : null; final GlobalSearchScope globalCustomScope = toGlobal(customScope); final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject); @@ -432,17 +432,7 @@ class FindInProjectTask { return Collections.emptySet(); } - SearchScope customScope = myFindModel.getCustomScope(); - GlobalSearchScope scope = myPsiDirectory != null - ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, myFindModel.isWithSubdirectories()) - : myModule != null - ? myModule.getModuleContentScope() - : customScope instanceof GlobalSearchScope - ? (GlobalSearchScope)customScope - : toGlobal(customScope); - if (scope == null) { - scope = ProjectScope.getContentScope(myProject); - } + GlobalSearchScope scope = toGlobal(FindInProjectUtil.getScopeFromModel(myProject, myFindModel)); final Set resultFiles = new LinkedHashSet(); diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java index 17ca7e4436bf..d22071e66b8e 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -49,10 +49,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.ex.VirtualFileManagerEx; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.GlobalSearchScopesCore; -import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.SearchScope; +import com.intellij.psi.search.*; import com.intellij.ui.content.Content; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewManager; @@ -443,7 +440,7 @@ public class FindInProjectUtil { } @NotNull - private static SearchScope getScopeFromModel(@NotNull Project project, @NotNull FindModel findModel) { + static SearchScope getScopeFromModel(@NotNull Project project, @NotNull FindModel findModel) { SearchScope customScope = findModel.getCustomScope(); PsiDirectory psiDir = getPsiDirectory(findModel, project); VirtualFile directory = psiDir == null ? null : psiDir.getVirtualFile(); @@ -452,8 +449,8 @@ public class FindInProjectUtil { // we don't have to check for myProjectFileIndex.isExcluded(file) here like FindInProjectTask.collectFilesInScope() does // because all found usages are guaranteed to be not in excluded dir directory != null ? GlobalSearchScopesCore.directoryScope(project, directory, findModel.isWithSubdirectories()) : - module != null ? GlobalSearchScope.moduleScope(module) : - findModel.isProjectScope() ? GlobalSearchScope.projectScope(project) : + module != null ? module.getModuleContentScope() : + findModel.isProjectScope() ? ProjectScope.getContentScope(project) : GlobalSearchScope.allScope(project); } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java index bed9f0267e4f..cabb8f3f2494 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java @@ -308,6 +308,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search if (mySearchResults.getMatchesCount() >= mySearchResults.getMatchesLimit()) return; for (FindResult range : mySearchResults.getOccurrences()) { + if (range.getEndOffset() > mySearchResults.getEditor().getDocument().getTextLength()) continue; TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES); if (range.getLength() == 0) { attributes = attributes.clone(); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java b/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java index 5a76d4bd52c7..46521faff6c5 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java @@ -99,8 +99,8 @@ public class TemplateKindCombo extends ComboboxWithBrowseButton { } private void scrollBy(int delta) { - if (delta == 0) return; final int size = getComboBox().getModel().getSize(); + if (delta == 0 || size == 0) return; int next = getComboBox().getSelectedIndex() + delta; if (next < 0 || next >= size) { if (!UISettings.getInstance().CYCLE_SCROLLING) { diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java index fef6554ca238..46075f81f4ae 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java @@ -29,7 +29,11 @@ public abstract class ScratchFileService { public enum Option { existing_only, create_if_missing, create_new_always } public static ScratchFileService getInstance() { - return ServiceManager.getService(ScratchFileService.class); + return ServiceHolder.instance; + } + + private static class ServiceHolder { + static final ScratchFileService instance = ServiceManager.getService(ScratchFileService.class); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java index 9526e0c597f9..40d4640133aa 100644 --- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java @@ -58,8 +58,7 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener } } } - for (Project project : myPlainTextFileSets.keySet()) { - Collection projectSet = myPlainTextFileSets.get(project); + for (Collection projectSet : myPlainTextFileSets.values()) { if (projectSet != null && projectSet.contains(file)) return true; } return false; diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java index 21d21d91e48f..b3d39daede51 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java @@ -57,6 +57,15 @@ import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Se * @since 7/20/12 1:56 PM */ public class ArrangementEngine { + private boolean myCodeChanged; + + @Nullable + public String getUserNotificationInfo() { + if (myCodeChanged) { + return "rearranged code"; + } + return null; + } /** * Arranges given PSI root contents that belong to the given ranges. @@ -87,8 +96,9 @@ public class ArrangementEngine { * @param file target PSI root * @param ranges target ranges to use within the given root */ - @SuppressWarnings("MethodMayBeStatic") public void arrange(@NotNull PsiFile file, @NotNull Collection ranges, @Nullable final ArrangementCallback callback) { + myCodeChanged = false; + final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); if (document == null) { return; @@ -143,7 +153,7 @@ public class ArrangementEngine { } @SuppressWarnings("unchecked") - private static void doArrange(Context context) { + private void doArrange(Context context) { // The general idea is to process entries bottom-up where every processed group belongs to the same parent. We may not bother // with entries text ranges then. We use a list and a stack for achieving that than. // @@ -363,8 +373,8 @@ public class ArrangementEngine { } @SuppressWarnings("unchecked") - private static void doArrange(@NotNull List> wrappers, - @NotNull Context context) { + private void doArrange(@NotNull List> wrappers, + @NotNull Context context) { if (wrappers.isEmpty()) { return; } @@ -408,7 +418,9 @@ public class ArrangementEngine { if (previous != null && previous.equals(previousInitial) || previous == null && previousInitial == null) { final int beforeOffset = arrangedWrapper.getStartOffset(); final int afterOffset = arrangedWrapper.getEndOffset(); - context.changer.insertSection(context, arranged.get(i), newSectionsInfo, parentWrapper, beforeOffset, afterOffset); + + boolean isInserted = context.changer.insertSection(context, arranged.get(i), newSectionsInfo, parentWrapper, beforeOffset, afterOffset); + myCodeChanged = isInserted || myCodeChanged; continue; } } @@ -416,6 +428,7 @@ public class ArrangementEngine { ArrangementEntryWrapper next = i < arranged.size() - 1 ? map.get(arranged.get(i + 1)) : null; context.changer.replace(arrangedWrapper, initialWrapper, previous, next, context); context.changer.insertSection(context, arranged.get(i), newSectionsInfo, arrangedWrapper, initialWrapper, parentWrapper); + myCodeChanged = true; } } @@ -600,7 +613,7 @@ public class ArrangementEngine { @NotNull ArrangementEntryWrapper initial, @Nullable ArrangementEntryWrapper parent); - protected abstract void insertSection(@NotNull Context context, + protected abstract boolean insertSection(@NotNull Context context, @NotNull E entry, @NotNull NewSectionInfo newSectionsInfo, @Nullable ArrangementEntryWrapper parent, int beforeOffset, int afterOffset); @@ -746,18 +759,22 @@ public class ArrangementEngine { } @Override - protected void insertSection(@NotNull Context context, + protected boolean insertSection(@NotNull Context context, @NotNull E entry, @NotNull NewSectionInfo newSectionsInfo, ArrangementEntryWrapper parent, int beforeOffset, int afterOffset) { + boolean isInserted = false; final String afterComment = newSectionsInfo.getEndComment(entry); if (afterComment != null) { insert(context, afterOffset, "\n" + afterComment); + isInserted = true; } final String beforeComment = newSectionsInfo.getStartComment(entry); if (beforeComment != null) { insert(context, beforeOffset, beforeComment + "\n"); + isInserted = true; } + return isInserted; } } @@ -886,24 +903,29 @@ public class ArrangementEngine { } @Override - protected void insertSection(@NotNull Context context, + protected boolean insertSection(@NotNull Context context, @NotNull E entry, @NotNull NewSectionInfo newSectionsInfo, @Nullable ArrangementEntryWrapper parent, int beforeOffset, int afterOffset) { + boolean isInserted = false; int diff = 0; final String afterComment = newSectionsInfo.getEndComment(entry); if (afterComment != null) { insert(context, afterOffset, "\n" + afterComment); diff += afterComment.length() + 1; + isInserted = true; } final String beforeComment = newSectionsInfo.getStartComment(entry); if (beforeComment != null) { insert(context, beforeOffset, beforeComment + "\n"); diff += beforeComment.length() + 1; + isInserted = true; } updateAllWrapperRanges(parent, diff); + + return isInserted; } /** diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java index aea68bf6d430..24d745373d4b 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java @@ -65,7 +65,7 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project); CommonCodeStyleSettings.IndentOptions userOptions = settings.getIndentOptions(psiFile.getFileType()); CommonCodeStyleSettings.IndentOptions detectedOptions = CodeStyleSettingsManager.getSettings(project).getIndentOptionsByFile( - psiFile, null, true, + psiFile, null, false, new Processor() { @Override public boolean process(FileIndentOptionsProvider provider) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java index 11b3a65a1318..4cae3d3eda6e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java @@ -49,9 +49,9 @@ class PersistableCodeStyleSchemes extends CodeStyleSchemesImpl implements Persis public Element getState() { return XmlSerializer.serialize(this, new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { if ("CURRENT_SCHEME_NAME".equals(accessor.getName())) { - return bean != null && !DEFAULT_SCHEME_NAME.equals(accessor.read(bean)); + return !DEFAULT_SCHEME_NAME.equals(accessor.read(bean)); } else { return accessor.getValueClass().equals(String.class); diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index 8b6843dab3ad..66f5de4179ad 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -46,7 +46,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubUpdatingIndex"); // todo remove once we don't need this for stub-ast mismatch debug info - private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 2, false); + private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 2, true); public static final ID INDEX_ID = ID.create("Stubs"); 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 55586b5e8b76..f80786273af7 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -390,8 +390,8 @@ class ValueContainerImpl extends UpdatableValueContainer implement return container; } - private void ensureFileSetCapacityForValue(Value value, int count) { - if (count <= 1) return; + private @Nullable ChangeBufferingList ensureFileSetCapacityForValue(Value value, int count) { + if (count <= 1) return null; Object fileSetObject = getFileSetObject(value); if (fileSetObject != null) { @@ -399,15 +399,18 @@ class ValueContainerImpl extends UpdatableValueContainer implement ChangeBufferingList list = new ChangeBufferingList(count + 1); list.add(((Integer)fileSetObject).intValue()); resetFileSetForValue(value, list); + return list; } else if (fileSetObject instanceof ChangeBufferingList) { ChangeBufferingList list = (ChangeBufferingList)fileSetObject; list.ensureCapacity(count); + return list; } - return; + return null; } - final Object fileSet = new ChangeBufferingList(count); + final ChangeBufferingList fileSet = new ChangeBufferingList(count); attachFileSetForNewValue(value, fileSet); + return fileSet; } private void attachFileSetForNewValue(Value value, Object fileSet) { @@ -551,12 +554,13 @@ class ValueContainerImpl extends UpdatableValueContainer implement if (mapping != null) mapping.associateFileIdToValue(idCountOrSingleValue, value); } else { idCountOrSingleValue = -idCountOrSingleValue; - ensureFileSetCapacityForValue(value, idCountOrSingleValue); + ChangeBufferingList changeBufferingList = ensureFileSetCapacityForValue(value, idCountOrSingleValue); int prev = 0; for (int i = 0; i < idCountOrSingleValue; i++) { final int id = DataInputOutputUtil.readINT(stream); - addValue(prev + id, value); + if (changeBufferingList != null) changeBufferingList.add(prev + id); + else addValue(prev + id, value); if (mapping != null) mapping.associateFileIdToValue(prev + id, value); prev += id; } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java index 1a631eae0b79..8c7f7905ff13 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull; import java.awt.*; public abstract class DiffManager { - public static DiffManager getInstance() { return ServiceManager.getService(DiffManager.class); } @@ -37,15 +36,15 @@ public abstract class DiffManager { * {@link DiffTool#HINT_SHOW_MODAL_DIALOG} force show diff in modal dialog
* {@link DiffTool#HINT_SHOW_FRAME} don't check modal window open. * Show diff in frame in any case. May help as workaround when closing - * modal dialog right before openning diff.
+ * modal dialog right before opening diff.
* {@link DiffTool#HINT_SHOW_NOT_MODAL_DIALOG} Show diff in not modal dialog
*/ public abstract DiffTool getIdeaDiffTool(); /** - * Work in progess. Don't rely on this functionality
+ * Work in progress. Don't rely on this functionality
* Adds new diff tool. - * + * * @param tool diff tool to register * @return false iff tool already registered (tool won't be registered twice). Otherwise true. * @throws NullPointerException iff tool == null @@ -53,9 +52,9 @@ public abstract class DiffManager { public abstract boolean registerDiffTool(DiffTool tool) throws NullPointerException; /** - * Work in progess. Don't rely on this functionality
- * Unregisters tool, registered with {@link #registerDiffTool(DiffTool)} - * + * Work in progress. Don't rely on this functionality
+ * Unregister tool, registered with {@link #registerDiffTool(DiffTool)} + * * @param tool diff tool to unregister */ public abstract void unregisterDiffTool(DiffTool tool); @@ -63,12 +62,11 @@ public abstract class DiffManager { public abstract MarkupEditorFilter getDiffEditorFilter(); /** - * - * @param window this window will be disposed, when user clicks on the line number - * You must call Disposer.dispose() when done. - * @param disposable - *@param parentTool @deprecated use {@link #createDiffPanel(Window, Project, Disposable)} instead + * @param window this window will be disposed, when user clicks on the line number + * You must call Disposer.dispose() when done. + * @param parentTool @deprecated use {@link #createDiffPanel(Window, Project, Disposable)} instead */ public abstract DiffPanel createDiffPanel(Window window, @NotNull Project project, DiffTool parentTool); + public abstract DiffPanel createDiffPanel(Window window, @NotNull Project project, @NotNull Disposable parentDisposable, DiffTool parentTool); } diff --git a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java index 73743f86d796..b988c6251e2e 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java +++ b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,10 +15,12 @@ */ package com.intellij.openapi.util.registry; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.diagnostic.Logger; import org.jdom.Element; -import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.SortedMap; @@ -26,9 +28,12 @@ import java.util.TreeMap; @State( name = "Registry", - storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") + storages = { + @Storage(file = StoragePathMacros.APP_CONFIG + "/ide.general.xml"), + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", deprecated = true) + } ) -public class RegistryState implements BaseComponent, PersistentStateComponent { +public class RegistryState implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance(RegistryState.class); @Override @@ -48,18 +53,4 @@ public class RegistryState implements BaseComponent, PersistentStateComponentid of tool window to be registered. * @param component component which represents tool window content. - * May be null. Content can be further added via content manager for this tool window (See {@link com.intellij.openapi.wm.ToolWindow#getContentManager()}) + * May be null. Content can be further added via content manager for this tool window (See {@link ToolWindow#getContentManager()}) * @param anchor the default anchor for first registration. It uses only first time the * tool window with the specified id is being registered into the window system. * After the first registration window's anchor is stored in project file * and anchor is ignored. - * @exception java.lang.IllegalArgumentException if the same window is already installed or one + * @exception IllegalArgumentException if the same window is already installed or one * of the parameters is null. * @return tool window - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor); /** - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull @@ -62,7 +66,7 @@ public abstract class ToolWindowManager { @NotNull Disposable parentDisposable); /** - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull @@ -72,7 +76,7 @@ public abstract class ToolWindowManager { Disposable parentDisposable, boolean canWorkInDumbMode); /** - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull diff --git a/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java b/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java index 4c46e2362e33..97b6e4d882c6 100644 --- a/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java +++ b/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.config; import com.intellij.openapi.util.Comparing; @@ -28,17 +27,28 @@ public abstract class AbstractProperty { } }; - @NonNls public abstract String getName(); + @NonNls + public abstract String getName(); + public abstract T getDefault(AbstractPropertyContainer container); + public abstract T copy(T value); public boolean areEqual(T value1, T value2) { return Comparing.equal(value1, value2); } - public T get(AbstractPropertyContainer container) { return (T) container.getValueOf(this); } - public void set(AbstractPropertyContainer container, T value) { container.setValueOf(this, value); } - public final T cast(Object value) { return (T) value; } + public T get(AbstractPropertyContainer container) { + return (T)container.getValueOf(this); + } + + public void set(AbstractPropertyContainer container, T value) { + container.setValueOf(this, value); + } + + public final T cast(Object value) { + return (T)value; + } public String toString() { return getName(); @@ -60,7 +70,9 @@ public abstract class AbstractProperty { }; protected abstract Object getValueOf(PropertyImpl property); + protected abstract void setValueOf(PropertyImpl property, Object value); + public abstract boolean hasProperty(AbstractProperty property); /** @@ -73,7 +85,7 @@ public abstract class AbstractProperty { /** * Only containers can delegate to another. - * Other clients should use {@link AbstractProperty#get AbstractProperty.get} + * Other clients should use {@link AbstractProperty#get AbstractProperty.get} */ protected final T delegateGet(AbstractPropertyContainer container, AbstractProperty property) { return (T)container.getValueOf(property); diff --git a/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java b/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java index 3f48ecf2a4b1..25f3a173e45b 100644 --- a/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java +++ b/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.config; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.util.SmartList; +import gnu.trove.THashMap; import org.jdom.Element; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; -public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPropertyContainer implements JDOMExternalizable { +public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPropertyContainer { private static final Logger LOG = Logger.getInstance(ExternalizablePropertyContainer.class); - private final Map myValues = new HashMap(); - private final Map myExternalizers = new HashMap(); + private final Map myValues = new THashMap(); + private final Map myExternalizers = new THashMap(); public void registerProperty(AbstractProperty property, Externalizer externalizer) { String name = property.getName(); @@ -66,37 +74,34 @@ public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPr registerProperty(property, itemTagName, Externalizer.FactoryBased.create(factory)); } - private Externalizer> createListExternalizer(final Externalizer itemExternalizer, final String itemTagName) { + private static Externalizer> createListExternalizer(final Externalizer itemExternalizer, final String itemTagName) { return new ListExternalizer(itemExternalizer, itemTagName); } - @Override - public void readExternal(Element element) throws InvalidDataException { - HashMap propertyByName = new HashMap(); + public void readExternal(@NotNull Element element) { + Map propertyByName = new THashMap(); for (AbstractProperty abstractProperty : myExternalizers.keySet()) { propertyByName.put(abstractProperty.getName(), abstractProperty); } - final List children = element.getChildren(); - for (Element child : children) { + for (Element child : element.getChildren()) { AbstractProperty property = propertyByName.get(child.getName()); if (property == null) { continue; } - final Externalizer externalizer = myExternalizers.get(property); + Externalizer externalizer = myExternalizers.get(property); if (externalizer == null) { continue; } try { myValues.put(property, externalizer.readValue(child)); } - catch (InvalidDataException e) { + catch (Exception e) { LOG.info(e); } } } - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void writeExternal(@NotNull Element element) { if (myExternalizers.isEmpty()) { return; } @@ -147,12 +152,12 @@ public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPr } @Override - public List readValue(Element dataElement) throws InvalidDataException { - ArrayList list = new ArrayList(); - List children = dataElement.getChildren(); - for (Iterator iterator = children.iterator(); iterator.hasNext();) { - Element element = iterator.next(); - if (NULL_ELEMENT.equals(element.getName())) list.add(null); + public List readValue(Element dataElement) { + List list = new SmartList(); + for (Element element : dataElement.getChildren()) { + if (NULL_ELEMENT.equals(element.getName())) { + list.add(null); + } else if (myItemTagName.equals(element.getName())) { T item = myItemExternalizer.readValue(element); if (item == null) { @@ -166,17 +171,17 @@ public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPr } @Override - public void writeValue(Element dataElement, List value) throws WriteExternalException { - for (Iterator iterator = value.iterator(); iterator.hasNext();) { - T item = iterator.next(); - if (item != null) { + public void writeValue(Element dataElement, List value) { + for (T item : value) { + if (item == null) { + dataElement.addContent(new Element(NULL_ELEMENT)); + } + else { Element element = new Element(myItemTagName); myItemExternalizer.writeValue(element, item); dataElement.addContent(element); } - else dataElement.addContent(new Element(NULL_ELEMENT)); } } } - } diff --git a/platform/platform-api/src/com/intellij/util/config/Externalizer.java b/platform/platform-api/src/com/intellij/util/config/Externalizer.java index 864b5bee0e43..1fb3eca0b262 100644 --- a/platform/platform-api/src/com/intellij/util/config/Externalizer.java +++ b/platform/platform-api/src/com/intellij/util/config/Externalizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -24,7 +24,6 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import java.util.Iterator; -import java.util.List; public interface Externalizer { @NonNls String VALUE_ATTRIBUTE = "value"; @@ -60,9 +59,9 @@ public interface Externalizer { } }; - T readValue(Element dataElement) throws InvalidDataException; + T readValue(Element dataElement); - void writeValue(Element dataElement, T value) throws WriteExternalException; + void writeValue(Element dataElement, T value); class FactoryBased implements Externalizer { private final Factory myFactory; @@ -72,15 +71,25 @@ public interface Externalizer { } @Override - public T readValue(Element dataElement) throws InvalidDataException { + public T readValue(Element dataElement) { T data = myFactory.create(); - data.readExternal(dataElement); + try { + data.readExternal(dataElement); + } + catch (InvalidDataException e) { + throw new RuntimeException(e); + } return data; } @Override - public void writeValue(Element dataElement, T value) throws WriteExternalException { - value.writeExternal(dataElement); + public void writeValue(Element dataElement, T value) { + try { + value.writeExternal(dataElement); + } + catch (WriteExternalException e) { + throw new RuntimeException(e); + } } public static FactoryBased create(Factory factory) { @@ -94,25 +103,25 @@ public interface Externalizer { @NonNls private static final String VALUE_ATTR = "value"; @Override - public Storage readValue(Element dataElement) throws InvalidDataException { + public Storage readValue(Element dataElement) { Storage.MapStorage storage = new Storage.MapStorage(); - List children = dataElement.getChildren(ITEM_TAG); - for (Iterator iterator = children.iterator(); iterator.hasNext();) { - Element element = iterator.next(); + for (Element element : dataElement.getChildren(ITEM_TAG)) { storage.put(element.getAttributeValue(KEY_ATTR), element.getAttributeValue(VALUE_ATTR)); } return storage; } @Override - public void writeValue(Element dataElement, Storage storage) throws WriteExternalException { + public void writeValue(Element dataElement, Storage storage) { Iterator keys = ((Storage.MapStorage)storage).getKeys(); while (keys.hasNext()) { String key = keys.next(); String value = storage.get(key); Element element = new Element(ITEM_TAG); element.setAttribute(KEY_ATTR, key); - if (value != null) element.setAttribute(VALUE_ATTR, value); + if (value != null) { + element.setAttribute(VALUE_ATTR, value); + } dataElement.addContent(element); } } diff --git a/platform/platform-impl/src/com/intellij/application/options/ShareSchemeDialog.java b/platform/platform-impl/src/com/intellij/application/options/ShareSchemeDialog.java deleted file mode 100644 index 22efc052e9ef..000000000000 --- a/platform/platform-impl/src/com/intellij/application/options/ShareSchemeDialog.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.application.options; - -import com.intellij.openapi.options.Scheme; -import com.intellij.openapi.ui.DialogWrapper; - -import javax.swing.*; - -public class ShareSchemeDialog extends DialogWrapper { - private final ShareSchemePanel myShareSchemePanel; - - public ShareSchemeDialog() { - super(true); - myShareSchemePanel = new ShareSchemePanel(); - setTitle("Share Scheme"); - init(); - } - - public void init(Scheme scheme){ - myShareSchemePanel.setName(scheme.getName()); - } - - protected JComponent createCenterPanel() { - return myShareSchemePanel.getPanel(); - } - - public String getName(){ - return myShareSchemePanel.getName(); - } - - public String getDescription(){ - return myShareSchemePanel.getDescription(); - } - -} diff --git a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.form b/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.form deleted file mode 100644 index e1082de419f1..000000000000 --- a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.form +++ /dev/null @@ -1,53 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.java b/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.java deleted file mode 100644 index 708004896633..000000000000 --- a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.application.options; - -import javax.swing.*; - - -public class ShareSchemePanel { - private JTextField mySharedSchemeName; - private JTextArea mySharedSchemeDescription; - private JPanel myPanel; - - public String getName(){ - return mySharedSchemeName.getText(); - } - - public String getDescription(){ - return mySharedSchemeDescription.getText(); - } - - public JPanel getPanel() { - return myPanel; - } - - public void setName(final String name) { - mySharedSchemeName.setText(name); - } -} diff --git a/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java b/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java index 0880e395308f..150dff080fe5 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java @@ -126,11 +126,7 @@ public class ConsoleViewUtil { @Override public Font getFont(EditorFontType key) { - Font font = super.getFont(EditorFontType.getConsoleType(key)); - if (font == null) { - return super.getFont(key); - } - return font; + return super.getFont(EditorFontType.getConsoleType(key)); } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java index b1839c87ac10..ad6a9567885c 100644 --- a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java @@ -215,7 +215,10 @@ public class StartupManagerImpl extends StartupManagerEx { } }); - Registry.get("ide.firstStartup").setValue(false); + // otherwise will be stored - we must not create config files in tests + if (!app.isUnitTestMode()) { + Registry.get("ide.firstStartup").setValue(false); + } } public void scheduleInitialVfsRefresh() { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java index 2df9bf7f6414..e1e77fb8354f 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,11 +15,8 @@ */ package com.intellij.ide.ui.laf; -import com.intellij.ide.ui.LafManager; import com.intellij.ide.ui.laf.darcula.DarculaLaf; -import com.intellij.openapi.util.SystemInfo; -import javax.swing.*; import javax.swing.plaf.metal.DefaultMetalTheme; /** @@ -36,19 +33,6 @@ public class IntelliJLaf extends DarculaLaf { return "intellijlaf"; } - @Override - public UIDefaults getDefaults() { - UIDefaults defaults = super.getDefaults(); - if (SystemInfo.isLinux) { - try { - LafManagerImpl.initFontDefaults(defaults, "Dialog", 12); - } - catch (Exception ignore) { - } - } - return defaults; - } - @Override protected DefaultMetalTheme createMetalTheme() { return new IdeaBlueMetalTheme(); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index 779e326d2802..0a2ce8d93e67 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -560,6 +560,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo List myIntKeys = Arrays.asList("Tree.leftChildIndent", "Tree.rightChildIndent"); + List patched = new ArrayList(); for (Map.Entry entry : defaults.entrySet()) { Object value = entry.getValue(); String key = entry.getKey().toString(); @@ -569,10 +570,16 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo entry.setValue(JBUI.insets(((InsetsUIResource)value)).asUIResource()); } else if (value instanceof Integer) { if (key.endsWith(".maxGutterIconWidth") || myIntKeys.contains(key)) { - entry.setValue(Integer.valueOf(JBUI.scale((Integer)value))); + if (!"true".equals(defaults.get(key +".hidpi.patched"))) { + entry.setValue(Integer.valueOf(JBUI.scale((Integer)value))); + patched.add(key); + } } } } + for (String key : patched) { + defaults.put(key + ".hidpi.patched", "true"); + } } public static void updateToolWindows() { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 156c39657609..14b5be48ce43 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -42,10 +42,8 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; -import java.util.Arrays; +import java.util.*; import java.util.List; -import java.util.Locale; -import java.util.Properties; /** * @author Konstantin Bulenkov @@ -91,6 +89,7 @@ public class DarculaLaf extends BasicLookAndFeel { final Method superMethod = BasicLookAndFeel.class.getDeclaredMethod("getDefaults"); superMethod.setAccessible(true); final UIDefaults metalDefaults = (UIDefaults)superMethod.invoke(new MetalLookAndFeel()); + final UIDefaults defaults = (UIDefaults)superMethod.invoke(base); if (SystemInfo.isLinux) { if (!Registry.is("darcula.use.native.fonts.on.linux")) { @@ -124,6 +123,9 @@ public class DarculaLaf extends BasicLookAndFeel { if (SystemInfo.isWindows) { //JFrame.setDefaultLookAndFeelDecorated(true); } + if (SystemInfo.isLinux && JBUI.isHiDPI()) { + applySystemFonts(defaults); + } defaults.put("EditorPane.font", defaults.getFont("TextField.font")); return defaults; } @@ -133,6 +135,23 @@ public class DarculaLaf extends BasicLookAndFeel { return super.getDefaults(); } + private static void applySystemFonts(UIDefaults defaults) { + try { + String fqn = UIManager.getSystemLookAndFeelClassName(); + Object systemLookAndFeel = Class.forName(fqn).newInstance(); + final Method superMethod = BasicLookAndFeel.class.getDeclaredMethod("getDefaults"); + superMethod.setAccessible(true); + final UIDefaults systemDefaults = (UIDefaults)superMethod.invoke(systemLookAndFeel); + for (Map.Entry entry : systemDefaults.entrySet()) { + if (entry.getValue() instanceof Font) { + defaults.put(entry.getKey(), entry.getValue()); + } + } + } catch (Exception e) { + log(e); + } + } + protected DefaultMetalTheme createMetalTheme() { return new DarculaMetalTheme(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java index 4547726a4834..9dda8602f086 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java @@ -20,7 +20,6 @@ import com.intellij.ide.actions.QuickSwitchSchemeAction; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.BundledQuickListsProvider; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ex.DecodeDefaultsUtil; import com.intellij.openapi.components.ExportableApplicationComponent; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.StoragePathMacros; @@ -31,12 +30,12 @@ import com.intellij.openapi.options.SchemesManagerFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.JDOMUtil; import com.intellij.util.PathUtilRt; +import com.intellij.util.ThrowableConvertor; import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import java.io.File; -import java.io.InputStream; import java.util.Collection; import java.util.Set; @@ -101,25 +100,17 @@ public class QuickListsManager implements ExportableApplicationComponent { @Override public void initComponent() { for (BundledQuickListsProvider provider : BundledQuickListsProvider.EP_NAME.getExtensions()) { - for (String path : provider.getBundledListsRelativePaths()) { - try { - InputStream inputStream = DecodeDefaultsUtil.getDefaultsInputStream(provider, path); - if (inputStream == null) { - // Error shouldn't occur during this operation thus we report error instead of info - LOG.error("Cannot read quick list from " + path); - } - else { - Element element = JDOMUtil.load(inputStream); + for (final String path : provider.getBundledListsRelativePaths()) { + mySchemesManager.loadBundledScheme(path, provider, new ThrowableConvertor() { + @Override + public QuickList convert(Element element) throws Throwable { QuickList item = createItem(element); item.getExternalInfo().setHash(JDOMUtil.getTreeHash(element, true)); item.getExternalInfo().setPreviouslySavedName(item.getName()); item.getExternalInfo().setCurrentFileName(PathUtilRt.getFileName(path)); - mySchemesManager.addNewScheme(item, false); + return item; } - } - catch (Exception e) { - LOG.error("Cannot read quick list from " + path + ": " + e.getMessage(), e); - } + }); } } mySchemesManager.loadSchemes(); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index 16c1567ed63d..8e15a8f61f78 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -22,7 +22,6 @@ import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.components.impl.stores.StateStorageManager.ExternalizationSession; import com.intellij.openapi.components.store.ReadOnlyModificationException; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; @@ -281,8 +280,12 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } Class stateClass = ComponentSerializationUtil.getStateClass(component.getClass()); - T state = getDefaultState(component, name, stateClass); + // todo remove assert before last EAP + if (!stateSpec.defaultStateAsResource() && getDefaultState(component, name, stateClass) != null) { + LOG.error(name + " has default state, but not marked to load it"); + } + T state = stateSpec.defaultStateAsResource() ? getDefaultState(component, name, stateClass) : null; Storage[] storageSpecs = getComponentStorageSpecs(component, stateSpec, StateStorageOperation.READ); for (Storage storageSpec : storageSpecs) { StateStorage stateStorage = getStateStorageManager().getStateStorage(storageSpec); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java index 2b755dbde9ca..5d7cd510c347 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -58,6 +58,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { return getStateCopy(); } + @NotNull @Override protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) { return new XmlElementStorageSaveSession(storageData) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java index 199d70123ca9..373d9c38f9a5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,14 +18,15 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.StateSplitter; +import com.intellij.openapi.components.StateStorageException; +import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.components.store.ReadOnlyModificationException; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.editor.DocumentRunnable; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -178,7 +179,7 @@ public class DirectoryBasedStorage extends StateStorageBase pair : storage.mySplitter.splitState(compositeState)) { + for (Pair pair : storage.mySplitter.splitState(element)) { removedFileNames.remove(pair.second); doSetState(componentName, pair.second, pair.first); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java index 53ac35c58ee3..1fdc5718aeb8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -94,6 +94,7 @@ public class FileBasedStorage extends XmlElementStorage { return isUseXmlProlog(); } + @NotNull @Override protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) { return new FileSaveSession(storageData); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java new file mode 100644 index 000000000000..9c100643314e --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2015 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.components.impl.stores; + +import com.intellij.openapi.components.StateStorage; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.util.xmlb.SkipDefaultsSerializationFilter; +import com.intellij.util.xmlb.XmlSerializer; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +abstract class SaveSessionBase implements StateStorage.SaveSession, StateStorage.ExternalizationSession { + private SkipDefaultsSerializationFilter serializationFilter; + + @SuppressWarnings("deprecation") + @Override + public final void setState(@NotNull Object component, @NotNull String componentName, @NotNull Object state, Storage storageSpec) { + Element element; + try { + if (state instanceof Element) { + element = (Element)state; + } + else if (state instanceof JDOMExternalizable) { + element = new Element("temp_element"); + ((JDOMExternalizable)state).writeExternal(element); + } + else { + if (serializationFilter == null) { + serializationFilter = new SkipDefaultsSerializationFilter(); + } + element = XmlSerializer.serializeIfNotDefault(state, serializationFilter); + } + } + catch (WriteExternalException e) { + StateStorageBase.LOG.debug(e); + return; + } + catch (Throwable e) { + StateStorageBase.LOG.error("Unable to serialize " + componentName + " state", e); + return; + } + + setSerializedState(component, componentName, element); + } + + protected abstract void setSerializedState(@NotNull Object component, @NotNull String componentName, @Nullable Element element); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/components/store/StateStorageBase.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.java similarity index 91% rename from platform/platform-impl/src/com/intellij/openapi/components/store/StateStorageBase.java rename to platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.java index da38c311e134..fb02c973e240 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/store/StateStorageBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.components.store; +package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; -import com.intellij.openapi.components.impl.stores.DefaultStateSerializer; -import com.intellij.openapi.components.impl.stores.StorageDataBase; import com.intellij.openapi.diagnostic.Logger; import org.jdom.Element; import org.jetbrains.annotations.NotNull; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java index 4b6624d6cad0..f1f7f1e308e8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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,11 +17,8 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.StateStorageException; -import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; @@ -133,6 +130,7 @@ public abstract class XmlElementStorage extends StateStorageBase { return checkIsSavingDisabled() ? null : createSaveSession(getStorageData()); } + @NotNull protected abstract XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData); @Nullable @@ -175,7 +173,7 @@ public abstract class XmlElementStorage extends StateStorageBase { } } - protected abstract class XmlElementStorageSaveSession implements SaveSession, ExternalizationSession { + protected abstract class XmlElementStorageSaveSession extends SaveSessionBase { private final StorageData myOriginalStorageData; private StorageData myCopiedStorageData; @@ -192,20 +190,7 @@ public abstract class XmlElementStorage extends StateStorageBase { } @Override - public final void setState(@NotNull Object component, @NotNull String componentName, @NotNull Object state, @Nullable Storage storageSpec) { - Element element; - try { - element = DefaultStateSerializer.serializeState(state, storageSpec); - } - catch (WriteExternalException e) { - LOG.debug(e); - return; - } - catch (Throwable e) { - LOG.error("Unable to serialize " + componentName + " state", e); - return; - } - + protected void setSerializedState(@NotNull Object component, @NotNull String componentName, @Nullable Element element) { if (myCopiedStorageData == null) { myCopiedStorageData = StorageData.setStateAndCloneIfNeed(componentName, element, myOriginalStorageData, myNewLiveStates); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java index bf07a4ad2cd1..7eb8000a7af3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -40,7 +40,7 @@ public interface DiffPanelEx extends DiffPanel, Disposable { DiffPanelOptions getOptions(); - void setComparisonPolicy(ComparisonPolicy comparisonPolicy); + void setComparisonPolicy(@NotNull ComparisonPolicy comparisonPolicy); ComparisonPolicy getComparisonPolicy(); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 7d1183a233c9..fbdde51e8761 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -180,17 +180,16 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid myDataProvider = new MyGenericDataProvider(this); myPanel.setDataProvider(myDataProvider); - final ComparisonPolicy comparisonPolicy = getComparisonPolicy(); - final ComparisonPolicy defaultComparisonPolicy = DiffManagerImpl.getInstanceEx().getComparisonPolicy(); - final HighlightMode highlightMode = getHighlightMode(); - final HighlightMode defaultHighlightMode = DiffManagerImpl.getInstanceEx().getHighlightMode(); + ComparisonPolicy comparisonPolicy = getComparisonPolicy(); + if (comparisonPolicy != DiffManagerImpl.getInstanceEx().getComparisonPolicy()) { + setComparisonPolicy(comparisonPolicy); + } - if (defaultComparisonPolicy != null && comparisonPolicy != defaultComparisonPolicy) { - setComparisonPolicy(defaultComparisonPolicy); - } - if (defaultHighlightMode != null && highlightMode != defaultHighlightMode) { - setHighlightMode(defaultHighlightMode); + HighlightMode highlightMode = getHighlightMode(); + if (highlightMode != DiffManagerImpl.getInstanceEx().getHighlightMode()) { + setHighlightMode(highlightMode); } + myVisibleAreaListener = new VisibleAreaListener() { @Override public void visibleAreaChanged(VisibleAreaEvent e) { @@ -504,11 +503,11 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid return myData.getComparisonPolicy(); } - public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) { + public void setComparisonPolicy(@NotNull ComparisonPolicy comparisonPolicy) { setComparisonPolicy(comparisonPolicy, true); } - private void setComparisonPolicy(ComparisonPolicy policy, boolean notifyManager) { + private void setComparisonPolicy(@NotNull ComparisonPolicy policy, boolean notifyManager) { myData.setComparisonPolicy(policy); rediff(); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java index d4948e11ee1a..15d51eec5d28 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,7 +18,10 @@ package com.intellij.openapi.diff.impl.external; import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.*; +import com.intellij.openapi.diff.DiffContent; +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.diff.DiffTool; +import com.intellij.openapi.diff.DiffViewer; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.UIBasedFileType; import org.jetbrains.annotations.NotNull; @@ -26,16 +29,21 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; class CompositeDiffTool implements DiffTool { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.external.CompositeDiffTool"); private final List myTools; - public CompositeDiffTool(List tools) { + public CompositeDiffTool(@NotNull List tools) { myTools = new ArrayList(tools); } + public CompositeDiffTool(@NotNull DiffTool[] tools) { + myTools = Arrays.asList(tools); + } + public void show(DiffRequest data) { checkDiffData(data); DiffTool tool = chooseTool(data); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java index aeb362bf68fe..2a842e99041d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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,10 @@ package com.intellij.openapi.diff.impl.external; import com.intellij.openapi.Disposable; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.DiffManager; import com.intellij.openapi.diff.DiffPanel; @@ -29,8 +33,11 @@ import com.intellij.openapi.diff.impl.processing.HighlightMode; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.markup.MarkupEditorFilter; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; +import com.intellij.util.SmartList; import com.intellij.util.config.*; +import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -39,8 +46,16 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; -public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { +@State( + name = "DiffManager", + storages = { + @Storage(file = StoragePathMacros.APP_CONFIG + "/diff.xml"), + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", deprecated = true) + } +) +public class DiffManagerImpl extends DiffManager implements PersistentStateComponent { public static final int FULL_DIFF_DIVIDER_POLYGONS_OFFSET = 3; private static final Logger LOG = Logger.getInstance(DiffManagerImpl.class); @@ -50,7 +65,10 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { @Override public String readValue(Element dataElement) { String path = dataElement.getAttributeValue(NEW_VALUE); - if (path != null) return path; + if (path != null) { + return path; + } + String prevValue = dataElement.getAttributeValue(VALUE_ATTRIBUTE); return prevValue != null ? prevValue.trim() : null; } @@ -70,9 +88,8 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { public static final BooleanProperty ENABLE_FILES = new BooleanProperty("enableFiles", false); public static final BooleanProperty ENABLE_MERGE = new BooleanProperty("enableMerge", false); - private final ExternalizablePropertyContainer myProperties; - private final ArrayList myAdditionTools = new ArrayList(); + private final List myAdditionTools = new SmartList(); public static final DiffTool INTERNAL_DIFF = new FrameDiffTool(); public static final Key EDITOR_IS_DIFF_KEY = new Key("EDITOR_IS_DIFF_KEY"); @@ -82,8 +99,9 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { return DiffUtil.isDiffEditor(editor); } }; - private ComparisonPolicy myComparisonPolicy; - private HighlightMode myHighlightMode; + + private ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT; + private HighlightMode myHighlightMode = HighlightMode.BY_WORD; @NonNls public static final String COMPARISON_POLICY_ATTR_NAME = "COMPARISON_POLICY"; @NonNls public static final String HIGHLIGHT_MODE_ATTR_NAME = "HIGHLIGHT_MODE"; @@ -100,13 +118,15 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { } @Override - public DiffTool getIdeaDiffTool() { return INTERNAL_DIFF; } + public DiffTool getIdeaDiffTool() { + return INTERNAL_DIFF; + } @Override public DiffTool getDiffTool() { DiffTool[] standardTools; // there is inner check in multiple tool for external viewers as well - if (! ENABLE_FILES.value(myProperties) || ! ENABLE_FOLDERS.value(myProperties) || !ENABLE_MERGE.value(myProperties)) { + if (!ENABLE_FILES.value(myProperties) || !ENABLE_FOLDERS.value(myProperties) || !ENABLE_MERGE.value(myProperties)) { DiffTool[] embeddableTools = { INTERNAL_DIFF, new MergeTool(), @@ -121,7 +141,8 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { new MergeTool(), BinaryDiffTool.INSTANCE }; - } else { + } + else { standardTools = new DiffTool[]{ ExtCompareFolders.INSTANCE, ExtCompareFiles.INSTANCE, @@ -131,14 +152,22 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { BinaryDiffTool.INSTANCE }; } - ArrayList allTools = new ArrayList(myAdditionTools); - allTools.addAll(Arrays.asList(standardTools)); - return new CompositeDiffTool(allTools); + if (myAdditionTools.isEmpty()) { + return new CompositeDiffTool(standardTools); + } + else { + List allTools = new ArrayList(myAdditionTools); + ContainerUtil.addAll(allTools, standardTools); + return new CompositeDiffTool(allTools); + } } @Override public boolean registerDiffTool(@NotNull DiffTool tool) throws NullPointerException { - if (myAdditionTools.contains(tool)) return false; + if (myAdditionTools.contains(tool)) { + return false; + } + myAdditionTools.add(tool); return true; } @@ -149,7 +178,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { LOG.assertTrue(!myAdditionTools.contains(tool)); } - public ArrayList getAdditionTools() { + public List getAdditionTools() { return myAdditionTools; } @@ -174,28 +203,35 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { return (DiffManagerImpl)DiffManager.getInstance(); } + @Nullable @Override - public void readExternal(@NotNull Element element) throws InvalidDataException { - myProperties.readExternal(element); - readPolicy(element); - readMode(element); + public Element getState() { + Element state = new Element("state"); + myProperties.writeExternal(state); + if (myComparisonPolicy != ComparisonPolicy.DEFAULT) { + state.setAttribute(COMPARISON_POLICY_ATTR_NAME, myComparisonPolicy.getName()); + } + if (myHighlightMode != HighlightMode.BY_WORD) { + state.setAttribute(HIGHLIGHT_MODE_ATTR_NAME, myHighlightMode.name()); + } + return state; } - private void readPolicy(@NotNull final Element element) { - final String policyName = element.getAttributeValue(COMPARISON_POLICY_ATTR_NAME); + @Override + public void loadState(Element state) { + myProperties.readExternal(state); + + String policyName = state.getAttributeValue(COMPARISON_POLICY_ATTR_NAME); if (policyName != null) { - ComparisonPolicy[] policies = ComparisonPolicy.getAllInstances(); - for (ComparisonPolicy policy : policies) { + for (ComparisonPolicy policy : ComparisonPolicy.getAllInstances()) { if (policy.getName().equals(policyName)) { myComparisonPolicy = policy; break; } } } - } - private void readMode(@NotNull final Element element) { - final String modeName = element.getAttributeValue(HIGHLIGHT_MODE_ATTR_NAME); + String modeName = state.getAttributeValue(HIGHLIGHT_MODE_ATTR_NAME); if (modeName != null) { try { myHighlightMode = HighlightMode.valueOf(modeName); @@ -205,19 +241,10 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { } } - @Override - public void writeExternal(@NotNull Element element) throws WriteExternalException { - myProperties.writeExternal(element); - if (myComparisonPolicy != null) { - element.setAttribute(COMPARISON_POLICY_ATTR_NAME, myComparisonPolicy.getName()); - } - if (myHighlightMode != null) { - element.setAttribute(HIGHLIGHT_MODE_ATTR_NAME, myHighlightMode.name()); - } + public AbstractProperty.AbstractPropertyContainer getProperties() { + return myProperties; } - public AbstractProperty.AbstractPropertyContainer getProperties() { return myProperties; } - static DiffPanel createDiffPanel(DiffRequest data, Window window, @NotNull Disposable parentDisposable, FrameDiffTool tool) { DiffPanel diffPanel = null; try { @@ -236,21 +263,21 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { } } - public void setComparisonPolicy(final ComparisonPolicy p) { - myComparisonPolicy = p; - } - - @Nullable + @NotNull public ComparisonPolicy getComparisonPolicy() { return myComparisonPolicy; } - public void setHighlightMode(HighlightMode highlightMode) { - myHighlightMode = highlightMode; + public void setComparisonPolicy(@NotNull ComparisonPolicy value) { + myComparisonPolicy = value; } - @Nullable + @NotNull public HighlightMode getHighlightMode() { return myHighlightMode; } + + public void setHighlightMode(@NotNull HighlightMode highlightMode) { + myHighlightMode = highlightMode; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java index b71eeda448a1..9fbb0b2cae55 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -28,7 +28,6 @@ import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.FrameWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ex.MessagesEx; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -40,8 +39,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collection; -// Author: dyoma - public class FrameDiffTool implements DiffTool { public void show(DiffRequest request) { Collection hints = request.getHints(); @@ -161,27 +158,27 @@ public class FrameDiffTool implements DiffTool { // TODO remove check? private boolean checkNoDifferenceAndNotify(DiffPanel diffPanel, DiffRequest data, final Window window, final boolean showMessage) { - if (!diffPanel.hasDifferences() && !data.getHints().contains(HINT_ALLOW_NO_DIFFERENCES)) { - DiffManagerImpl manager = (DiffManagerImpl) DiffManager.getInstance(); - if (!Comparing.equal(manager.getComparisonPolicy(), ComparisonPolicy.DEFAULT)) { - ComparisonPolicy oldPolicy = manager.getComparisonPolicy(); - manager.setComparisonPolicy(ComparisonPolicy.DEFAULT); - Disposable parentDisposable = Disposer.newDisposable(); - DiffPanel maybeDiffPanel = DiffManagerImpl.createDiffPanel(data, window, parentDisposable, this); - manager.setComparisonPolicy(oldPolicy); - - boolean hasDiffs = maybeDiffPanel.hasDifferences(); - Disposer.dispose(parentDisposable); - - if (hasDiffs) return false; - } - - if (! showMessage) { - return true; - } - return !askForceOpenDiff(data); + if (diffPanel.hasDifferences() || data.getHints().contains(HINT_ALLOW_NO_DIFFERENCES)) { + return false; } - return false; + + DiffManagerImpl manager = (DiffManagerImpl)DiffManager.getInstance(); + ComparisonPolicy oldPolicy = manager.getComparisonPolicy(); + if (oldPolicy != ComparisonPolicy.DEFAULT) { + manager.setComparisonPolicy(ComparisonPolicy.DEFAULT); + Disposable parentDisposable = Disposer.newDisposable(); + DiffPanel maybeDiffPanel = DiffManagerImpl.createDiffPanel(data, window, parentDisposable, this); + manager.setComparisonPolicy(oldPolicy); + + boolean hasDiffs = maybeDiffPanel.hasDifferences(); + Disposer.dispose(parentDisposable); + + if (hasDiffs) { + return false; + } + } + + return !showMessage || !askForceOpenDiff(data); } private static boolean askForceOpenDiff(DiffRequest data) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java index fc26cf634e88..ccaa5190e587 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diff.impl.ComparisonPolicy; import com.intellij.openapi.diff.impl.ContentChangeListener; -import com.intellij.openapi.diff.impl.fragments.*; +import com.intellij.openapi.diff.impl.fragments.FragmentHighlighterImpl; +import com.intellij.openapi.diff.impl.fragments.FragmentList; +import com.intellij.openapi.diff.impl.fragments.FragmentListImpl; +import com.intellij.openapi.diff.impl.fragments.LineFragment; import com.intellij.openapi.diff.impl.processing.DiffPolicy; import com.intellij.openapi.diff.impl.processing.HighlightMode; import com.intellij.openapi.diff.impl.processing.TextCompareProcessor; @@ -58,7 +61,7 @@ public abstract class SimpleDiffPanelState implements Disposable { return editorWrapper; } - public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) { + public void setComparisonPolicy(@NotNull ComparisonPolicy comparisonPolicy) { myComparisonPolicy = comparisonPolicy; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java index b5662c6ab49f..69e4f7b2991e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java @@ -17,12 +17,12 @@ package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; +import com.intellij.openapi.project.DumbAware; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; * @author Denis Zhdanov * @since Aug 23, 2010 11:33:35 AM */ -public abstract class AbstractToggleUseSoftWrapsAction extends ToggleAction { +public abstract class AbstractToggleUseSoftWrapsAction extends ToggleAction implements DumbAware { private final SoftWrapAppliancePlaces myAppliancePlace; private final boolean myGlobal; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java index 1089d5e54e3e..01fe0814f2c3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java @@ -18,8 +18,6 @@ package com.intellij.openapi.editor.colors.impl; import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.FontSize; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -145,11 +143,7 @@ public abstract class DelegateColorScheme implements EditorColorsScheme { } @Override - public void readExternal(Element element) throws InvalidDataException { - } - - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void readExternal(Element element) { } @NotNull @@ -203,5 +197,4 @@ public abstract class DelegateColorScheme implements EditorColorsScheme { public void setConsoleLineSpacing(float lineSpacing) { myDelegate.setConsoleLineSpacing(lineSpacing); } - } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java index a433a1d6f445..e4a8a78c5698 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java @@ -13,21 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/** - * @author Yura Cangea - */ package com.intellij.openapi.editor.colors.impl; import com.intellij.ide.WelcomeWizardUtil; import com.intellij.ide.ui.LafManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.components.ExportableComponent; -import com.intellij.openapi.components.NamedComponent; -import com.intellij.openapi.components.RoamingType; -import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.colors.EditorColorsListener; @@ -36,55 +28,109 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.options.*; -import com.intellij.openapi.util.*; +import com.intellij.openapi.options.BaseSchemeProcessor; +import com.intellij.openapi.options.Scheme; +import com.intellij.openapi.options.SchemesManager; +import com.intellij.openapi.options.SchemesManagerFactory; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.EventDispatcher; +import com.intellij.util.ThrowableConvertor; +import com.intellij.util.io.URLUtil; import com.intellij.util.ui.UIUtil; +import com.intellij.util.xmlb.annotations.OptionTag; import org.jdom.Element; -import org.jdom.JDOMException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.net.URL; import java.util.Arrays; import java.util.Comparator; import java.util.List; -public class EditorColorsManagerImpl extends EditorColorsManager implements NamedJDOMExternalizable, ExportableComponent, NamedComponent { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl"); +@State( + name = "EditorColorsManagerImpl", + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/colors.scheme.xml"), + additionalExportFile = EditorColorsManagerImpl.FILE_SPEC +) +public class EditorColorsManagerImpl extends EditorColorsManager implements PersistentStateComponent { + private static final Logger LOG = Logger.getInstance(EditorColorsManagerImpl.class); - private final EventDispatcher myListeners = EventDispatcher.create(EditorColorsListener.class); - - @NonNls private static final String NODE_NAME = "global_color_scheme"; @NonNls private static final String SCHEME_NODE_NAME = "scheme"; private static final String DEFAULT_NAME = "Default"; - private String myGlobalSchemeName; - public boolean USE_ONLY_MONOSPACED_FONTS = true; + private final EventDispatcher myListeners = EventDispatcher.create(EditorColorsListener.class); + private final DefaultColorSchemesManager myDefaultColorSchemesManager; private final SchemesManager mySchemesManager; - @NonNls private static final String NAME_ATTR = "name"; - private static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/colors"; - @NonNls - private static final String FILE_EXT = ".icls"; + static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/colors"; + + private State myState = new State(); public EditorColorsManagerImpl(DefaultColorSchemesManager defaultColorSchemesManager, SchemesManagerFactory schemesManagerFactory) { myDefaultColorSchemesManager = defaultColorSchemesManager; - mySchemesManager = schemesManagerFactory.createSchemesManager( - FILE_SPEC, - new MySchemeProcessor(), RoamingType.PER_USER); + mySchemesManager = schemesManagerFactory.createSchemesManager(FILE_SPEC, new BaseSchemeProcessor() { + @NotNull + @Override + public EditorColorsSchemeImpl readScheme(@NotNull Element element) { + EditorColorsSchemeImpl scheme = new EditorColorsSchemeImpl(null); + scheme.readExternal(element); + return scheme; + } + + @Override + public Element writeScheme(@NotNull final EditorColorsSchemeImpl scheme) { + Element root = new Element(SCHEME_NODE_NAME); + try { + scheme.writeExternal(root); + } + catch (WriteExternalException e) { + LOG.error(e); + return null; + } + return root; + } + + @NotNull + @Override + public State getState(@NotNull EditorColorsSchemeImpl scheme) { + return scheme instanceof ReadOnlyColorsScheme ? State.NON_PERSISTENT : State.POSSIBLY_CHANGED; + } + + @Override + public void onCurrentSchemeChanged(final Scheme newCurrentScheme) { + fireChanges(mySchemesManager.getCurrentScheme()); + } + + @NotNull + @NonNls + @Override + public String getSchemeExtension() { + return ".icls"; + } + + @Override + public boolean isUpgradeNeeded() { + return true; + } + }, RoamingType.PER_USER); addDefaultSchemes(); // Load default schemes from providers if (!isUnitTestOrHeadlessMode()) { - loadSchemesFromBeans(); + for (BundledColorSchemeEP ep : BundledColorSchemeEP.EP_NAME.getExtensions()) { + mySchemesManager.loadBundledScheme(ep.path + ".xml", ep, new ThrowableConvertor() { + @Override + public EditorColorsScheme convert(Element element) throws Throwable { + return new ReadOnlyColorsSchemeImpl(element); + } + }); + } } mySchemesManager.loadSchemes(); @@ -97,8 +143,22 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name scheme = getScheme(wizardEditorScheme); LOG.assertTrue(scheme != null, "Wizard scheme " + wizardEditorScheme + " not found"); } - if (scheme == null) scheme = myDefaultColorSchemesManager.getAllSchemes()[0]; - setGlobalSchemeInner(scheme); + setGlobalSchemeInner(scheme == null ? getDefaultScheme() : scheme); + } + + static class ReadOnlyColorsSchemeImpl extends EditorColorsSchemeImpl implements ReadOnlyColorsScheme { + public ReadOnlyColorsSchemeImpl(@NotNull Element element) { + super(null); + + readExternal(element); + } + } + + static class State { + public boolean USE_ONLY_MONOSPACED_FONTS = true; + + @OptionTag(tag = "global_color_scheme", nameAttribute = "", valueAttribute = "name") + public String colorScheme; } private static boolean isUnitTestOrHeadlessMode() { @@ -110,29 +170,12 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name // It is reasonable to fetch attributes from Default color scheme. Otherwise if we launch IDE and then // try switch from custom colors scheme (e.g. with dark background) to default one. Editor will show // incorrect highlighting with "traces" of color scheme which was active during IDE startup. - final EditorColorsScheme defaultColorScheme = getScheme(dark ? "Darcula" : EditorColorsScheme.DEFAULT_SCHEME_NAME); - return defaultColorScheme.getAttributes(key); - } - - private void loadSchemesFromBeans() { - for (BundledColorSchemeEP schemeEP : Extensions.getExtensions(BundledColorSchemeEP.EP_NAME)) { - String fileName = schemeEP.path + ".xml"; - InputStream stream = schemeEP.getLoaderForClass().getResourceAsStream(fileName); - try { - EditorColorsSchemeImpl scheme = loadSchemeFromStream(fileName, stream); - if (scheme != null) { - mySchemesManager.addNewScheme(scheme, false); - } - } - catch (final Exception e) { - LOG.error("Cannot read scheme from " + fileName + ": " + e.getLocalizedMessage(), e); - } - } + return getScheme(dark ? "Darcula" : EditorColorsScheme.DEFAULT_SCHEME_NAME).getAttributes(key); } private void loadAdditionalTextAttributes() { for (AdditionalTextAttributesEP attributesEP : AdditionalTextAttributesEP.EP_NAME.getExtensions()) { - final EditorColorsScheme editorColorsScheme = mySchemesManager.findSchemeByName(attributesEP.scheme); + EditorColorsScheme editorColorsScheme = mySchemesManager.findSchemeByName(attributesEP.scheme); if (editorColorsScheme == null) { if (!isUnitTestOrHeadlessMode()) { LOG.warn("Cannot find scheme: " + attributesEP.scheme + " from plugin: " + attributesEP.getPluginDescriptor().getPluginId()); @@ -140,57 +183,19 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name continue; } try { - InputStream inputStream = attributesEP.getLoaderForClass().getResourceAsStream(attributesEP.file); - ((AbstractColorsScheme)editorColorsScheme).readAttributes(JDOMUtil.load(inputStream)); + URL resource = attributesEP.getLoaderForClass().getResource(attributesEP.file); + assert resource != null; + ((AbstractColorsScheme)editorColorsScheme).readAttributes(JDOMUtil.load(URLUtil.openStream(resource))); } - catch (Exception e1) { - LOG.error(e1); + catch (Exception e) { + LOG.error(e); } } } - private static EditorColorsSchemeImpl loadSchemeFromStream(String schemePath, InputStream inputStream) - throws IOException, JDOMException, InvalidDataException { - if (inputStream == null) { - // Error shouldn't occur during this operation - // thus we report error instead of info - LOG.error("Cannot read scheme from " + schemePath); - return null; - } - - Element element; - try { - element = JDOMUtil.load(inputStream); - } - catch (JDOMException e) { - LOG.info("Error reading scheme from " + schemePath + ": " + e.getLocalizedMessage()); - throw e; - } - return loadSchemeFromDocument(element, false); - } - - @NotNull - private static EditorColorsSchemeImpl loadSchemeFromDocument(@NotNull Element element, boolean isEditable) throws InvalidDataException { - if (!SCHEME_NODE_NAME.equals(element.getName())) { - throw new InvalidDataException(); - } - - final EditorColorsSchemeImpl scheme = isEditable - // editable scheme - ? new EditorColorsSchemeImpl(null, DefaultColorSchemesManager.getInstance()) - //not editable scheme - : new ReadOnlyColorsSchemeImpl(null, DefaultColorSchemesManager.getInstance()); - scheme.readExternal(element); - return scheme; - } - - // ------------------------------------------------------------------------- - // Schemes manipulation routines - // ------------------------------------------------------------------------- - @Override public void addColorsScheme(@NotNull EditorColorsScheme scheme) { - if (!isDefaultScheme(scheme) && scheme.getName().trim().length() > 0) { + if (!isDefaultScheme(scheme) && !StringUtil.isEmpty(scheme.getName())) { mySchemesManager.addNewScheme(scheme, true); } } @@ -202,16 +207,11 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } private void addDefaultSchemes() { - DefaultColorsScheme[] allDefaultSchemes = myDefaultColorSchemesManager.getAllSchemes(); - for (DefaultColorsScheme defaultScheme : allDefaultSchemes) { + for (DefaultColorsScheme defaultScheme : myDefaultColorSchemesManager.getAllSchemes()) { mySchemesManager.addNewScheme(defaultScheme, true); } } - // ------------------------------------------------------------------------- - // Getters & Setters - // ------------------------------------------------------------------------- - @NotNull @Override public EditorColorsScheme[] getAllSchemes() { @@ -245,18 +245,15 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } @NotNull - private static DefaultColorsScheme getDefaultScheme() { - return DefaultColorSchemesManager.getInstance().getAllSchemes()[0]; + private DefaultColorsScheme getDefaultScheme() { + return myDefaultColorSchemesManager.getAllSchemes()[0]; } @NotNull @Override public EditorColorsScheme getGlobalScheme() { - final EditorColorsScheme scheme = mySchemesManager.getCurrentScheme(); - if (scheme == null) { - return getDefaultScheme(); - } - return scheme; + EditorColorsScheme scheme = mySchemesManager.getCurrentScheme(); + return scheme == null ? getDefaultScheme() : scheme; } @Override @@ -268,24 +265,6 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name myListeners.getMulticaster().globalSchemeChange(scheme); } - // ------------------------------------------------------------------------- - // Routines responsible for loading & saving colors schemes. - // ------------------------------------------------------------------------- - - private static File getColorsDir(boolean create) { - @NonNls String directoryPath = PathManager.getConfigPath() + File.separator + "colors"; - File directory = new File(directoryPath); - if (!directory.exists()) { - if (!create) return null; - if (!directory.mkdir()) { - LOG.error("Cannot create directory: " + directory.getAbsolutePath()); - return null; - } - } - return directory; - } - - @Override public void addEditorColorsListener(@NotNull EditorColorsListener listener) { myListeners.addListener(listener); @@ -302,56 +281,29 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } @Override - public void setUseOnlyMonospacedFonts(boolean b) { - USE_ONLY_MONOSPACED_FONTS = b; + public void setUseOnlyMonospacedFonts(boolean value) { + myState.USE_ONLY_MONOSPACED_FONTS = value; } @Override public boolean isUseOnlyMonospacedFonts() { - return USE_ONLY_MONOSPACED_FONTS; + return myState.USE_ONLY_MONOSPACED_FONTS; } + @Nullable @Override - public String getExternalFileName() { - return "colors.scheme"; - } - - @Override - @NotNull - public File[] getExportFiles() { - return new File[]{getColorsDir(true), PathManager.getOptionsFile(this)}; - } - - @Override - @NotNull - public String getPresentableName() { - return OptionsBundle.message("options.color.schemes.presentable.name"); - } - - @Override - public void readExternal(Element parentNode) throws InvalidDataException { - DefaultJDOMExternalizer.readExternal(this, parentNode); - Element element = parentNode.getChild(NODE_NAME); - if (element != null) { - String name = element.getAttributeValue(NAME_ATTR); - if (StringUtil.isNotEmpty(name)) { - myGlobalSchemeName = name; - } - } - - EditorColorsScheme globalScheme = - myGlobalSchemeName != null ? mySchemesManager.findSchemeByName(myGlobalSchemeName) : myDefaultColorSchemesManager.getAllSchemes()[0]; - setGlobalSchemeInner(globalScheme); - } - - @Override - public void writeExternal(Element parentNode) throws WriteExternalException { - DefaultJDOMExternalizer.writeExternal(this, parentNode); + public State getState() { if (mySchemesManager.getCurrentScheme() != null) { - Element element = new Element(NODE_NAME); - element.setAttribute(NAME_ATTR, mySchemesManager.getCurrentScheme().getName()); - parentNode.addContent(element); + String name = mySchemesManager.getCurrentScheme().getName(); + myState.colorScheme = "Default".equals(name) ? null : name; } + return myState; + } + + @Override + public void loadState(State state) { + myState = state; + setGlobalSchemeInner(myState.colorScheme == null ? getDefaultScheme() : mySchemesManager.findSchemeByName(myState.colorScheme)); } @Override @@ -359,57 +311,8 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name return scheme instanceof DefaultColorsScheme; } + @TestOnly public SchemesManager getSchemesManager() { return mySchemesManager; } - - @Override - @NotNull - public String getComponentName() { - return "EditorColorsManagerImpl"; - } - - private final class MySchemeProcessor extends BaseSchemeProcessor implements SchemeExtensionProvider { - @NotNull - @Override - public EditorColorsSchemeImpl readScheme(@NotNull Element element) throws InvalidDataException { - return loadSchemeFromDocument(element, true); - } - - @Override - public Element writeScheme(@NotNull final EditorColorsSchemeImpl scheme) { - Element root = new Element(SCHEME_NODE_NAME); - try { - scheme.writeExternal(root); - } - catch (WriteExternalException e) { - LOG.error(e); - return null; - } - - return root; - } - - @NotNull - @Override - public State getState(@NotNull EditorColorsSchemeImpl scheme) { - return scheme instanceof ReadOnlyColorsScheme ? State.NON_PERSISTENT : State.POSSIBLY_CHANGED; - } - - @Override - public void onCurrentSchemeChanged(final Scheme newCurrentScheme) { - fireChanges(mySchemesManager.getCurrentScheme()); - } - - @NotNull - @Override - public String getSchemeExtension() { - return FILE_EXT; - } - - @Override - public boolean isUpgradeNeeded() { - return true; - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/ReadOnlyColorsSchemeImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/ReadOnlyColorsSchemeImpl.java deleted file mode 100644 index f7a777edb96f..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/ReadOnlyColorsSchemeImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.editor.colors.impl; - -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; - -/** - * @author Roman Chernyatchik - */ -public class ReadOnlyColorsSchemeImpl extends EditorColorsSchemeImpl implements ReadOnlyColorsScheme { - public ReadOnlyColorsSchemeImpl(final EditorColorsScheme parenScheme, - final DefaultColorSchemesManager defaultColorSchemesManager) { - super(parenScheme, defaultColorSchemesManager); - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java index 95a4ab25444b..866bc141d47f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java @@ -63,19 +63,6 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP return myEditor.visualPositionToXY(magnificationPosition); } }); - putClientProperty("sun.lwawt.macosx.CInputMethod.selectPreviousGlyph.callback", new Runnable() { - @Override - public void run() { - // This is supposed to be called from sun.lwawt.macosx.CInputMethod class of a custom JDK, - // built for IntelliJ platform running on MacOS. - // This is required to support input of accented characters using press-and-hold method (http://support.apple.com/kb/PH11264). - // Non-patched JDK supports this functionality only for TextComponent/JTextComponent descendants. - int caretOffset = myEditor.getCaretModel().getOffset(); - if (caretOffset > 0) { - myEditor.getSelectionModel().setSelection(caretOffset - 1, caretOffset); - } - } - }); myApplication = (ApplicationImpl)ApplicationManager.getApplication(); } 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 fcdbe2fc4147..ea0ce0da254b 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 @@ -308,6 +308,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi public final boolean myUseNewRendering = Registry.is("editor.new.rendering"); final EditorView myView; + private boolean myCharKeyPressed; + private boolean myNeedToSelectPreviousChar; + private final TIntFunction myLineNumberAreaWidthFunction = new TIntFunction() { @Override public int execute(int lineNumber) { @@ -902,9 +905,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myPanel.add(myScrollPane); } - myEditorComponent.addKeyListener(new KeyAdapter() { + myEditorComponent.addKeyListener(new KeyListener() { @Override public void keyTyped(@NotNull KeyEvent event) { + myNeedToSelectPreviousChar = false; if (event.isConsumed()) { return; } @@ -912,6 +916,18 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi event.consume(); } } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() >= KeyEvent.VK_A && e.getKeyCode() <= KeyEvent.VK_Z) { + myCharKeyPressed = true; + } + } + + @Override + public void keyReleased(KeyEvent e) { + myCharKeyPressed = false; + } }); MyMouseAdapter mouseAdapter = new MyMouseAdapter(); @@ -5413,6 +5429,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @Override @Nullable public AttributedCharacterIterator getSelectedText(AttributedCharacterIterator.Attribute[] attributes) { + if (myCharKeyPressed) { + myNeedToSelectPreviousChar = true; + } String text = getSelectionModel().getSelectedText(); return text == null ? null : new AttributedString(text).getIterator(); } @@ -5457,6 +5476,22 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } private void replaceInputMethodText(@NotNull InputMethodEvent e) { + if (myNeedToSelectPreviousChar && SystemInfo.isMac && Registry.is("ide.mac.pressAndHold.workaround")) { + // This is required to support input of accented characters using press-and-hold method (http://support.apple.com/kb/PH11264). + // JDK currently properly supports this functionality only for TextComponent/JTextComponent descendants. + // For our editor component we need this workaround. + myNeedToSelectPreviousChar = false; + getCaretModel().runForEachCaret(new CaretAction() { + @Override + public void perform(Caret caret) { + int caretOffset = caret.getOffset(); + if (caretOffset > 0) { + caret.setSelection(caretOffset - 1, caretOffset); + } + } + }); + } + int commitCount = e.getCommittedCharacterCount(); AttributedCharacterIterator text = e.getText(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index d39877081825..e234be4f0b2a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -185,6 +185,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi if ((myUseSoftWraps ^ softWrapsUsedBefore) || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore) || fontsChanged) { myApplianceManager.reset(); myDeferredFoldRegions.clear(); + myStorage.removeAll(); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); } } @@ -286,9 +287,6 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi * @return total number of soft wrap-introduced new visual lines */ public int getSoftWrapsIntroducedLinesNumber() { - if (!isSoftWrappingEnabled()) { - return 0; - } return myStorage.getSoftWraps().size(); // Assuming that soft wrap has single line feed all the time } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java index a8243ab67d1b..03714165fa24 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java @@ -18,6 +18,7 @@ package com.intellij.openapi.options; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.DecodeDefaultsUtil; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.StateStorageException; @@ -27,6 +28,7 @@ import com.intellij.openapi.components.impl.stores.StorageUtil; import com.intellij.openapi.components.impl.stores.StreamProvider; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.DocumentRunnable; +import com.intellij.openapi.extensions.AbstractExtensionPointBean; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.InvalidDataException; @@ -41,7 +43,9 @@ import com.intellij.openapi.vfs.VirtualFileAdapter; import com.intellij.openapi.vfs.VirtualFileEvent; import com.intellij.openapi.vfs.tracker.VirtualFileTracker; import com.intellij.util.SmartList; +import com.intellij.util.ThrowableConvertor; import com.intellij.util.containers.ContainerUtilRt; +import com.intellij.util.io.URLUtil; import com.intellij.util.text.UniqueNameGenerator; import gnu.trove.THashSet; import org.jdom.Document; @@ -55,6 +59,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URL; import java.util.*; public class SchemesManagerImpl extends AbstractSchemesManager { @@ -69,7 +74,7 @@ public class SchemesManagerImpl myFilesToDelete = new THashSet(); @@ -85,7 +90,7 @@ public class SchemesManagerImpl convertor) { + try { + URL url = requestor instanceof AbstractExtensionPointBean + ? (((AbstractExtensionPointBean)requestor).getLoaderForClass().getResource(resourceName)) + : DecodeDefaultsUtil.getDefaults(requestor, resourceName); + if (url == null) { + // Error shouldn't occur during this operation thus we report error instead of info + LOG.error("Cannot read scheme from " + resourceName); + return; + } + addNewScheme(convertor.convert(JDOMUtil.load(URLUtil.openStream(url))), false); + } + catch (Throwable e) { + LOG.error("Cannot read scheme from " + resourceName, e); + } + } + private boolean isMy(@NotNull VirtualFileEvent event) { return StringUtilRt.endsWithIgnoreCase(event.getFile().getNameSequence(), mySchemeExtension); } @@ -316,15 +338,17 @@ public class SchemesManagerImpl myUpdatesQueue = new Queue(5); /** @@ -116,6 +117,11 @@ public class DumbServiceImpl extends DumbService implements Disposable { myAlternativeResolution.set(enabled); } + @Override + public ModificationTracker getModificationTracker() { + return null; + } + @Override public boolean isDumb() { return myDumb; @@ -209,6 +215,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { @Override public Boolean compute() { myDumb = true; + myModificationCount++; try { myPublisher.enteredDumbMode(); } @@ -236,6 +243,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { private void updateFinished() { myDumb = false; + myModificationCount++; if (myProject.isDisposed()) return; if (ApplicationManager.getApplication().isInternal()) LOG.info("updateFinished"); @@ -440,6 +448,11 @@ public class DumbServiceImpl extends DumbService implements Disposable { return result.get(); } + @Override + public long getModificationCount() { + return myModificationCount; + } + private class AppIconProgress extends ProgressIndicatorBase { private double lastFraction; diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index f12e25ba113d..401d3e5f9c09 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -29,12 +29,8 @@ import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.components.*; -import com.intellij.openapi.components.impl.stores.ComponentStoreImpl; +import com.intellij.openapi.components.impl.stores.*; import com.intellij.openapi.components.impl.stores.ComponentStoreImpl.ReloadComponentStoreStatus; -import com.intellij.openapi.components.impl.stores.FileBasedStorage; -import com.intellij.openapi.components.impl.stores.StateStorageManager; -import com.intellij.openapi.components.impl.stores.StorageUtil; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.*; diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java index 7717de4a616d..28af087d7816 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -41,6 +41,7 @@ import com.intellij.openapi.wm.impl.IdeGlassPaneEx; import com.intellij.ui.FocusTrackback; import com.intellij.ui.ScreenUtil; import com.intellij.ui.components.JBLayeredPane; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -591,7 +592,7 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc } private void createShadow() { - if (!UISettings.isRemoteDesktopConnected()) { + if (!UISettings.isRemoteDesktopConnected() && !JBUI.isHiDPI()) { shadow = ShadowBorderPainter.createShadow(this, getWidth(), getHeight()); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java index 4bb301ba7918..4062cd2f317d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java @@ -62,7 +62,8 @@ import java.util.Set; */ @State( name = "WindowManager", - storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/window.manager.xml", roamingType = RoamingType.DISABLED)} + defaultStateAsResource = true, + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/window.manager.xml", roamingType = RoamingType.DISABLED) ) public final class WindowManagerImpl extends WindowManagerEx implements NamedComponent, PersistentStateComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowManagerImpl"); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java index b01c167917d9..3b89e81eb1f5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java @@ -20,7 +20,8 @@ import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileEditor.impl.EditorsSplitters; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; @@ -42,13 +43,7 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, @NotNull public Icon getIcon() { - Project project = getProject(); - VirtualFile virtualFile = null; - if (project != null) { - FileEditorManager editorManager = FileEditorManager.getInstance(project); - VirtualFile[] selectedFiles = editorManager.getSelectedFiles(); - virtualFile = selectedFiles.length > 0 ? selectedFiles[0] : null; - } + VirtualFile virtualFile = getCurrentFile(); return virtualFile == null || virtualFile.isWritable() ? AllIcons.Ide.Readwrite : AllIcons.Ide.Readonly; } @@ -82,13 +77,8 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, public Consumer getClickConsumer() { return new Consumer() { public void consume(MouseEvent mouseEvent) { - final Project project = getProject(); - if (project == null) { - return; - } - final FileEditorManager editorManager = FileEditorManager.getInstance(project); - final VirtualFile[] files = editorManager.getSelectedFiles(); - if (!isReadOnlyApplicableForFiles(files)) { + final VirtualFile file = getCurrentFile(); + if (!isReadOnlyApplicableForFile(file)) { return; } FileDocumentManager.getInstance().saveAllDocuments(); @@ -96,11 +86,11 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { try { - ReadOnlyAttributeUtil.setReadOnlyAttribute(files[0], files[0].isWritable()); + ReadOnlyAttributeUtil.setReadOnlyAttribute(file, file.isWritable()); myStatusBar.updateWidget(ID()); } catch (IOException e) { - Messages.showMessageDialog(project, e.getMessage(), UIBundle.message("error.dialog.title"), Messages.getErrorIcon()); + Messages.showMessageDialog(getProject(), e.getMessage(), UIBundle.message("error.dialog.title"), Messages.getErrorIcon()); } } }); @@ -109,20 +99,24 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, } private boolean isReadonlyApplicable() { - final Project project = getProject(); - if (project == null) return false; - final FileEditorManager editorManager = FileEditorManager.getInstance(project); - if (editorManager == null) return false; - VirtualFile[] selectedFiles = editorManager.getSelectedFiles(); - return isReadOnlyApplicableForFiles(selectedFiles); + VirtualFile file = getCurrentFile(); + return isReadOnlyApplicableForFile(file); } - private static boolean isReadOnlyApplicableForFiles(final VirtualFile[] files) { - return files.length > 0 && !files[0].getFileSystem().isReadOnly(); + private static boolean isReadOnlyApplicableForFile(@Nullable VirtualFile file) { + return file != null && !file.getFileSystem().isReadOnly(); } @Nullable private Project getProject() { return CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext((JComponent) myStatusBar)); } + + @Nullable + private VirtualFile getCurrentFile() { + final Project project = getProject(); + if (project == null) return null; + EditorsSplitters splitters = FileEditorManagerEx.getInstanceEx(project).getSplittersFor(myStatusBar.getComponent()); + return splitters.getCurrentFile(); + } } diff --git a/platform/platform-impl/src/com/intellij/ui/Splash.java b/platform/platform-impl/src/com/intellij/ui/Splash.java index 0bee1412af15..fcab3aa223ab 100644 --- a/platform/platform-impl/src/com/intellij/ui/Splash.java +++ b/platform/platform-impl/src/com/intellij/ui/Splash.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -47,7 +47,7 @@ public class Splash extends JDialog implements StartupProgress { @Nullable public static Rectangle BOUNDS; private final Icon myImage; - private int myProgressHeight = 2; + private int myProgressHeight = JBUI.scale(2); private Color myProgressColor = null; private int myProgressY; private float myProgress; @@ -102,7 +102,7 @@ public class Splash extends JDialog implements StartupProgress { this(info.getSplashImageUrl(), info.getSplashTextColor()); if (info instanceof ApplicationInfoImpl) { final ApplicationInfoImpl appInfo = (ApplicationInfoImpl)info; - myProgressHeight = 2; + myProgressHeight = JBUI.scale(2); myProgressColor = appInfo.getProgressColor(); myProgressY = appInfo.getProgressY(); myProgressTail = appInfo.getProgressTailIcon(); @@ -143,8 +143,8 @@ public class Splash extends JDialog implements StartupProgress { g.setColor(color); g.fillRect(1, getProgressY(), width, getProgressHeight()); if (myProgressTail != null) { - myProgressTail.paintIcon(this, g, width - (myProgressTail.getIconWidth()/2), - getProgressY() - (myProgressTail.getIconHeight() - getProgressHeight())/2); + myProgressTail.paintIcon(this, g, width - (myProgressTail.getIconWidth() / JBUI.scale(1) / 2 * JBUI.scale(1)), + getProgressY() - (myProgressTail.getIconHeight() - getProgressHeight()) / JBUI.scale(1) / 2 * JBUI.scale(1)); //I'll buy you a beer if you understand this line without playing with it } myProgressLastPosition = progressWidth; } diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java index 1415af6cbcd0..0dc92839a0f2 100644 --- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java +++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java @@ -225,6 +225,7 @@ public final class NettyUtil { .allowCredentials() .allowNullOrigin() .allowedRequestMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.HEAD, HttpMethod.PATCH) + .allowedRequestHeaders("origin", "accept", "authorization", "content-type") .build())); } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index df4aa168e8fa..89f48f1340cc 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -228,8 +228,8 @@ action.NewClass.text=Java Class action.NewFile.text=File action.NewDir.text=Directory/Package action.NewFromTemplate.text=From Template -action.CompareTwoFiles.text=Compare Two _Files -action.CompareTwoFiles.description=Compare two selected files +action.CompareTwoFiles.text=Compare _Files +action.CompareTwoFiles.description=Compare two selected files or folders action.CompareFileWithEditor.text=Co_mpare File with Editor action.CompareFileWithEditor.description=Compare selected file with editor action.ShowQuickDocAtPinnedWindowFromTooltip.text=Full documentation in a pinned window @@ -548,6 +548,7 @@ action.OptimizeImports.text=Optimi_ze Imports... action.OptimizeImports.description=Remove unused imports and reorder/reorganize imports action.RearrangeCode.text=Rearrange Code action.RearrangeCode.description=Rearrange code +action.ShowReformatFileDialog.text=Show Reformat File Dialog action.MoveStatementDown.text=Move Statement Do_wn action.MoveStatementDown.description=Move selected statements one line down action.MoveStatementUp.text=Move Statement _Up diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index 4c4a14eb79b4..0e2cdb791edb 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -7,6 +7,7 @@ reformat.directory.dialog.filters=Filters process.scope.directory=Directory ''{0}'' process.scope.project=Project ''{0}'' process.scope.module=Module ''{0}'' +process.scope.changed.files=only VCS changed files reformat.code.accept.button.text=Run process.scope.file=&File {0} reformat.option.selected.text=&Selected text @@ -25,6 +26,7 @@ progress.reformat.and.optimize.common.command.text=Reformat and Optimize Imports progress.reformat.stage.wrapping.blocks=Preparing... progress.reformat.stage.processing.blocks=Calculating changes... progress.reformat.stage.applying.changes=Storing changes... +process.rearrange.code=Rearranging code... process.reformat.code=Reformat Code process.reformat.code.before.commit=Reformat Code Before Commit process.rearrange.code.before.commit=Rearrange Code Before Commit @@ -230,8 +232,10 @@ intention.create.test.dialog.class.name=Class name: intention.create.test.dialog.super.class=Superclass: intention.create.test.dialog.choose.super.class=Choose Superclass intention.create.test.dialog.generate=Generate: -intention.create.test.dialog.show.inherited=Show inherited methods -intention.create.test.dialog.select.methods=Generate test methods for: +intention.create.test.dialog.show.inherited=Show &inherited methods +intention.create.test.dialog.setUp=set&Up/@Before +intention.create.test.dialog.tearDown=tear&Down/@After +intention.create.test.dialog.select.methods=Generate test &methods for: intention.create.test.dialog.library.not.found={0} library not found in the module intention.create.test.dialog.fix.library=Fix intention.create.test.dialog.java=Java diff --git a/platform/platform-resources-en/src/messages/OptionsBundle.properties b/platform/platform-resources-en/src/messages/OptionsBundle.properties index 761cb2400667..4972ee89de88 100644 --- a/platform/platform-resources-en/src/messages/OptionsBundle.properties +++ b/platform/platform-resources-en/src/messages/OptionsBundle.properties @@ -252,7 +252,6 @@ project.file.read.only.error.message=The project file is read-only.\nThe setting template.project.settings.display.name=Template Project Settings #0 - project name project.settings.display.name=Project Settings [{0}] -options.color.schemes.presentable.name=Color schemes options.java.attribute.descriptor.weak.warning=Weak Warning options.java.attribute.descriptor.server.problems=Problem from server options.java.attribute.descriptor.server.duplicate=Duplicate from server @@ -315,4 +314,5 @@ exportable.CodeStyleSchemeSettings.presentable.name=Code Style exportable.InspectionProfileManager.presentable.name=Inspection profiles exportable.TodoConfiguration.presentable.name=Todo exportable.UISettings.presentable.name=UI Settings -exportable.FileTypeManager.presentable.name=File types \ No newline at end of file +exportable.FileTypeManager.presentable.name=File types +exportable.EditorColorsManager.presentable.name=Color schemes \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index e8ce7ae50d9c..a16d0325abbf 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -241,5 +241,6 @@ + diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index d156e5efda6a..66c338b02eb1 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -167,7 +167,6 @@ serviceImplementation="com.intellij.openapi.editor.colors.impl.TextAttributeKeyDefaultsProviderImpl"/> - diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index b7f76e554855..d9fe7ef3fa2b 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -1,18 +1,18 @@ // This file contains list of broken plugins. // Each line contains plugin ID and list of versions that are broken. // If plugin name or version contains a space you can quote it like in command line. -NodeJS 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 +NodeJS 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 com.jetbrains.php 139.732 139.659 139.496 139.173 139.105 138.2502 138.2000.2262 138.1751 138.1806 138.1505 138.1161 138.826 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12 com.jetbrains.lang.ejs 131.17 131.12 com.jetbrains.twig 133.51 130.1639 -org.jetbrains.plugins.ruby 7.0.0.20141010 7.0.0.20140915 7.0.0.20140901 7.0.0.20140807 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707 7.0.0.20140724 +org.jetbrains.plugins.ruby 7.0.0.20150216 7.0.0.20150204 7.0.0.20141010 7.0.0.20140915 7.0.0.20140901 7.0.0.20140807 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707 7.0.0.20140724 Pythonid 3.1 4.0.25 4.0.26 -Karma 138.1684 138.1879 138.317 138.21 134.1163 134.1039 134.686 134.31 -org.intellij.scala 1.0.93.10.EAP 1.0.93.4.EAP 1.0.93.9.EAP 1.0.58 1.0.16 1.0.14 1.0.13 0.42.28 0.42.23 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512 +Karma 140.2109 138.1684 138.1879 138.317 138.21 134.1163 134.1039 134.686 134.31 +org.intellij.scala 1.2.67.3.EAP 1.3.2-14.1 1.3.3-14.1 1.0.93.10.EAP 1.0.93.4.EAP 1.0.93.9.EAP 1.0.58 1.0.16 1.0.14 1.0.13 0.42.28 0.42.23 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512 org.jetbrains.kannotator 0.2.420 org.jetbrains.kotlin 0.10.555 0.10.4 0.8.1615 0.7.1360 0.7.1376 0.8.7 SBT 1.0.0 1.1.0 1.2.0 1.3.0 1.3.1 1.4.0 1.5.0 1.5.1 1.6.0 1.6.1 -"JSTestDriver Plugin" 140.1669 140.727 138.317 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039 +"JSTestDriver Plugin" 140.2109 140.1669 140.727 138.317 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039 AngularJS 139.1112 139.12 134.1243 134.1341 134.1444 135.1063 135.565 135.831 135.937 138.1242 138.1988 134.1094 0.1.8 0.1.9 com.jetbrains.plugins.ini4idea 0.4 0.5 0.6 0.7 0.8 0.8.1 0.9 0.9.1 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 130.1176 org.jetbrains.plugins.vagrant 0.1 0.2 diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index 9f51364fa5a0..5ce4479f0491 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -87,6 +87,9 @@ + + + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 9db13bc456b1..cc37df8bfb68 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -938,5 +938,7 @@ + + diff --git a/platform/platform-tests/testData/codeStyle/formatter/addedLines.java b/platform/platform-tests/testData/codeStyle/formatter/addedLines.java new file mode 100644 index 000000000000..909aa3180175 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/addedLines.java @@ -0,0 +1,23 @@ +public class Add { + + public void run() { + int a = 1; + a = 2; + a = 3; + a = 4; + a = 5; + a = 6; + a = 7; + a = 8; + a = 9; + a = 10; + a = 11; + a = 12; + a = 13; + a = 14; + a = 15; + a = 16; + a = 17; + } + +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/addedLines_revision.java b/platform/platform-tests/testData/codeStyle/formatter/addedLines_revision.java new file mode 100644 index 000000000000..282dbcfeab31 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/addedLines_revision.java @@ -0,0 +1,7 @@ +public class Add { + + public void run() { + + } + +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted.java b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted.java new file mode 100644 index 000000000000..6c39c1530e29 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted.java @@ -0,0 +1,9 @@ +public class ChangedAndDeleted { + + public void run() { + String a = "12"; + int f = 31; + int g = 33; + String b = "3"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted_revision.java b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted_revision.java new file mode 100644 index 000000000000..ea11b6b07260 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted_revision.java @@ -0,0 +1,12 @@ +public class ChangedAndDeleted { + + public void run() { + int a = 2; + int b = 3; + int c = 4; + int d = 12; + int e = 212; + int f = 31; + int g = 33; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine.java b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine.java new file mode 100644 index 000000000000..5433fda2e122 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine.java @@ -0,0 +1,6 @@ +public class SingleLine { + + public void run() { + String a = "1"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine_revision.java b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine_revision.java new file mode 100644 index 000000000000..3fab16a816e7 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine_revision.java @@ -0,0 +1,6 @@ +public class SingleLine { + + public void run() { + int a = 2; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/deletedLines.java b/platform/platform-tests/testData/codeStyle/formatter/deletedLines.java new file mode 100644 index 000000000000..4e04525f61ee --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/deletedLines.java @@ -0,0 +1,7 @@ +public class DeletedLines { + + public void run() { + int a = 1; + int e = 5; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/deletedLines_revision.java b/platform/platform-tests/testData/codeStyle/formatter/deletedLines_revision.java new file mode 100644 index 000000000000..31f696d10c23 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/deletedLines_revision.java @@ -0,0 +1,10 @@ +public class DeletedLines { + + public void run() { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/insert.java b/platform/platform-tests/testData/codeStyle/formatter/insert.java new file mode 100644 index 000000000000..e34fddabbbc8 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/insert.java @@ -0,0 +1,10 @@ +public class Insert { + + public void run() { + int a = 1; + int b = 3; + int c = 4; + String a = "aa"; + String b = "bb"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/insert_revision.java b/platform/platform-tests/testData/codeStyle/formatter/insert_revision.java new file mode 100644 index 000000000000..34959832ab08 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/insert_revision.java @@ -0,0 +1,8 @@ +public class Insert { + + public void run() { + int a = 1; + int b = 3; + int c = 4; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces.java b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces.java new file mode 100644 index 000000000000..e08516436124 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces.java @@ -0,0 +1,6 @@ +public class WhiteSpaces { + + public void run() { + + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces_revision.java b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces_revision.java new file mode 100644 index 000000000000..30257da33a66 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces_revision.java @@ -0,0 +1,25 @@ +public class WhiteSpaces { + + + + + + + + + + + + + + + + + + + + + public void run() { + + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modification.java b/platform/platform-tests/testData/codeStyle/formatter/modification.java new file mode 100644 index 000000000000..f7ebb94eb68b --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modification.java @@ -0,0 +1,8 @@ +public class Modify { + + public void run() { + int a = 1; + String ad = "s"; + int d = 6; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modification_revision.java b/platform/platform-tests/testData/codeStyle/formatter/modification_revision.java new file mode 100644 index 000000000000..647ce258cf1e --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modification_revision.java @@ -0,0 +1,10 @@ +public class Modify { + + public void run() { + int a = 1; + int b = 3; + int c = 4; + int f = 5; + int d = 6; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modifiedLines.java b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines.java new file mode 100644 index 000000000000..70fc21e037c1 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines.java @@ -0,0 +1,11 @@ +public class Modified { + + public void run() { + String a = "1"; + String b = "2"; + String c = "3"; + String d = "4"; + String e = "5"; + String f = "6"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modifiedLines_revision.java b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines_revision.java new file mode 100644 index 000000000000..a4b60339bfdf --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines_revision.java @@ -0,0 +1,8 @@ +public class Modified { + + public void run() { + int a = 1; + int b = 2; + int c = 3; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLinesCounterTest.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLinesCounterTest.java new file mode 100644 index 000000000000..724e1e1d502d --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLinesCounterTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2000-2015 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.actions; + +import com.intellij.openapi.editor.Document; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import org.junit.Assert; + +import java.io.File; + +public class ChangedLinesCounterTest extends LightPlatformCodeInsightFixtureTestCase { + + static { + PlatformTestCase.initPlatformLangPrefix(); + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + + "/platform/platform-tests/testData/" + + "codeStyle/formatter/"; + } + + @Override + public void tearDown() throws Exception { + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); + super.tearDown(); + } + + public void doTest(int expectedLinesChanged) { + myFixture.configureByFile(getTestName(true) + "_revision.java"); + PsiFile file = myFixture.getFile(); + CharSequence revisionContent = myFixture.getDocument(file).getCharsSequence(); + + myFixture.configureByFile(getTestName(true) + ".java"); + file = myFixture.getFile(); + Document document = myFixture.getDocument(file); + + int linesChanged = FormatChangedTextUtil.calculateChangedLinesNumber(document, revisionContent); + Assert.assertTrue(linesChanged > 0); + Assert.assertEquals(expectedLinesChanged, linesChanged); + } + + public void testAddedLines() { + doTest(17); + } + + public void testModifiedLines() { + doTest(6); + } + + public void testDeletedLines() { + doTest(3); + } + + public void testChangedSingleLine() { + doTest(1); + } + + public void testChangedAndDeleted() { + doTest(6); + } + + public void testModification() { + doTest(3); + } + + public void testInsert() { + doTest(2); + } + + public void testLotsWhiteSpaces() { + doTest(19); + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java index 34f6874b9da9..0fafc897cdad 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -94,6 +94,7 @@ public class XmlElementStorageTest extends LightPlatformLangTestCase { return myElement; } + @NotNull @Override protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) { return new XmlElementStorageSaveSession(storageData) { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java index 675f6715f201..348dc0d94bfc 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java @@ -19,6 +19,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.testFramework.LightPlatformCodeInsightTestCase; +import com.intellij.testFramework.PlatformTestCase; import org.jdom.Element; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; @@ -28,12 +29,14 @@ import java.io.StringWriter; import java.util.Arrays; import java.util.Collections; -import static com.intellij.openapi.editor.colors.FontPreferencesTest.checkState; -import static com.intellij.openapi.editor.colors.FontPreferencesTest.getAnotherExistingNonDefaultFontName; -import static com.intellij.openapi.editor.colors.FontPreferencesTest.getExistingNonDefaultFontName; +import static com.intellij.openapi.editor.colors.FontPreferencesTest.*; public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase { - EditorColorsSchemeImpl myScheme = new EditorColorsSchemeImpl(null, null); + EditorColorsSchemeImpl myScheme = new EditorColorsSchemeImpl(null); + + static { + PlatformTestCase.initPlatformLangPrefix(); + } public void testDefaults() { checkState(myScheme.getFontPreferences(), @@ -173,7 +176,7 @@ public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase EditorColorsScheme editorColorsScheme = (EditorColorsScheme)defaultScheme.clone(); editorColorsScheme.setName("test"); Element root = new Element("scheme"); - editorColorsScheme.writeExternal(root); + ((AbstractColorsScheme)editorColorsScheme).writeExternal(root); root.removeChildren("option"); // Remove font options assertXmlOutputEquals("", root); } @@ -183,7 +186,7 @@ public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase EditorColorsScheme editorColorsScheme = (EditorColorsScheme)darculaScheme.clone(); editorColorsScheme.setName("test"); Element root = new Element("scheme"); - editorColorsScheme.writeExternal(root); + ((AbstractColorsScheme)editorColorsScheme).writeExternal(root); root.removeChildren("option"); // Remove font options assertXmlOutputEquals("", root); } diff --git a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java index 3e38bd2bbb4a..a4fd1b4c881b 100644 --- a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java @@ -25,6 +25,11 @@ import com.intellij.usages.UsageTarget; import com.intellij.usages.UsageViewManager; public class UsageViewManagerTest extends PlatformTestCase { + + static { + initPlatformLangPrefix(); + } + public void testScopeCreatedForFindInDirectory() { VirtualFile dir = getProject().getBaseDir(); FindModel findModel = new FindModel(); @@ -36,4 +41,14 @@ public class UsageViewManagerTest extends PlatformTestCase { SearchScope scope = manager.getMaxSearchScopeToWarnOfFallingOutOf(new UsageTarget[]{target}); assertEquals(scope, GlobalSearchScopesCore.directoryScope(getProject(), dir, true)); } + + public void testScopeCreatedForFindInModuleContent() { + FindModel findModel = new FindModel(); + findModel.setModuleName(getModule().getName()); + findModel.setProjectScope(false); + UsageTarget target = new FindInProjectUtil.StringUsageTarget(getProject(), findModel); + UsageViewManagerImpl manager = (UsageViewManagerImpl)UsageViewManager.getInstance(getProject()); + SearchScope scope = manager.getMaxSearchScopeToWarnOfFallingOutOf(new UsageTarget[]{target}); + assertEquals(scope, getModule().getModuleContentScope()); + } } diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/State.java b/platform/projectModel-api/src/com/intellij/openapi/components/State.java index 35cddbd5d16a..6db1cec2205d 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/State.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/State.java @@ -36,6 +36,11 @@ public @interface State { boolean reloadable() default true; + /** + * If true, default state will be loaded from resources (if exists) + */ + boolean defaultStateAsResource() default false; + String additionalExportFile() default ""; Class presentableName() default NameGetter.class; diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java b/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java index 152cc036347c..0bdcbbfa6f28 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -24,8 +24,12 @@ import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface Storage { @NonNls String id() default "default"; + + @Deprecated boolean isDefault() default true; + @NonNls String file() default ""; + StorageScheme scheme() default StorageScheme.DEFAULT; /** @@ -39,5 +43,6 @@ public @interface Storage { RoamingType roamingType() default RoamingType.PER_USER; Class storageClass() default StateStorage.class; + Class stateSplitter() default StateSplitterEx.class; } diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java b/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java index 0baf9e6ebd05..d00e69aae56e 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.openapi.components; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) +@Deprecated public @interface StorageId { String value(); } \ No newline at end of file diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java index d882ca15be83..3d1bb2240528 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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,20 +16,14 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.StateStorageException; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.components.StorageId; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.ReflectionUtil; -import com.intellij.util.xmlb.Accessor; -import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; import com.intellij.util.xmlb.XmlSerializationException; import com.intellij.util.xmlb.XmlSerializer; import org.jdom.Element; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @SuppressWarnings({"deprecation"}) @@ -39,37 +33,6 @@ public class DefaultStateSerializer { private DefaultStateSerializer() { } - @Nullable - static Element serializeState(@NotNull Object state, @Nullable final Storage storage) throws WriteExternalException { - if (state instanceof Element) { - return (Element)state; - } - else if (state instanceof JDOMExternalizable) { - Element element = new Element("temp_element"); - ((JDOMExternalizable)state).writeExternal(element); - return element; - } - else { - return XmlSerializer.serializeIfNotDefault(state, new SkipDefaultValuesSerializationFilters() { - @Override - protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { - if (!super.accepts(accessor, bean, beanValue)) { - return false; - } - - if (storage != null) { - StorageId storageId = accessor.getAnnotation(StorageId.class); - if (storageId != null && !storageId.value().equals(storage.id())) { - return false; - } - return storage.isDefault(); - } - return true; - } - }); - } - } - @SuppressWarnings({"unchecked"}) @Nullable public static T deserializeState(@Nullable Element stateElement, Class stateClass, @Nullable T mergeInto) throws XmlSerializationException { diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java index 397e04ef9f59..cf4d40ab9eb7 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 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.debugger.sourcemap; import com.google.gson.stream.JsonToken; @@ -98,7 +113,7 @@ public final class SourceMapDecoder { else if (propertyName.equals("sourceRoot")) { sourceRoot = readSourcePath(reader); if (sourceRoot != null) { - sourceRoot = UriUtil.trimLeadingSlashes(sourceRoot); + sourceRoot = UriUtil.trimTrailingSlashes(sourceRoot); } } else if (propertyName.equals("sources")) { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java index 4c21d8f6892b..be7277b31572 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java @@ -23,7 +23,7 @@ public class MatchOptions implements JDOMExternalizable { private boolean recursiveSearch; private boolean caseSensitiveMatch; private boolean resultIsContextMatch = false; - private FileType myFileType = StructuralSearchUtil.getDefaultFileType(); + private FileType myFileType = null; private Language myDialect = null; private SearchScope scope; @@ -77,9 +77,9 @@ public class MatchOptions implements JDOMExternalizable { return null; } - public Iterator getVariableConstraintNames() { - if (variableConstraints==null) return null; - return variableConstraints.keySet().iterator(); + public Set getVariableConstraintNames() { + if (variableConstraints==null) return Collections.emptySet(); + return Collections.unmodifiableSet(variableConstraints.keySet()); } public void setCaseSensitiveMatch(boolean caseSensitiveMatch) { @@ -268,8 +268,7 @@ public class MatchOptions implements JDOMExternalizable { } public int hashCode() { - int result; - result = (looseMatching ? 1 : 0); + int result = (looseMatching ? 1 : 0); result = 29 * result + (recursiveSearch ? 1 : 0); result = 29 * result + (caseSensitiveMatch ? 1 : 0); // @TODO support scope @@ -285,6 +284,9 @@ public class MatchOptions implements JDOMExternalizable { } public FileType getFileType() { + if (myFileType == null) { + myFileType = StructuralSearchUtil.getDefaultFileType(); + } return myFileType; } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java b/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java index 594686e14d49..747c17625095 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java @@ -4,7 +4,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.structuralsearch.impl.matcher.MatcherImpl; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -75,10 +75,10 @@ public class Matcher extends MatcherImpl { * @throws MalformedPatternException * @throws UnsupportedPatternException */ - @Nullable - public MatchResult isMatchedByDownUp(PsiElement element,MatchOptions options) throws + @NotNull + public List matchByDownUp(PsiElement element, MatchOptions options) throws MalformedPatternException, UnsupportedPatternException { - return super.isMatchedByDownUp(element, options); + return super.matchByDownUp(element, options); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java index 678b99cf2146..1597f2f2d87b 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java @@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.SoftReference; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -627,15 +628,11 @@ public class MatcherImpl { } } - @Nullable - protected MatchResult isMatchedByDownUp(PsiElement element, final MatchOptions options) { + @NotNull + protected List matchByDownUp(PsiElement element, final MatchOptions options) { final CollectingMatchResultSink sink = new CollectingMatchResultSink(); - CompiledPattern compiledPattern = prepareMatching(sink, options); - - if (compiledPattern== null) { - assert false; - return null; - } + final CompiledPattern compiledPattern = prepareMatching(sink, options); + matchContext.setShouldRecursivelyMatch(false); PsiElement targetNode = compiledPattern.getTargetNode(); PsiElement elementToStartMatching = null; @@ -647,21 +644,26 @@ public class MatcherImpl { assert !compiledPattern.getNodes().hasNext(); compiledPattern.getNodes().rewind(); + element = element.getParent(); + if (element == null) { + return Collections.emptyList(); + } while (element.getClass() != targetNode.getClass()) { element = element.getParent(); - if (element == null) return null; + if (element == null) return Collections.emptyList(); } elementToStartMatching = element; } } else { - targetNode = StructuralSearchUtil.getProfileByPsiElement(element).extendMatchedByDownUp(targetNode); + final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(element); + if (profile == null) return Collections.emptyList(); + targetNode = profile.extendMatchedByDownUp(targetNode); MatchingHandler handler = null; while (element.getClass() == targetNode.getClass() || - compiledPattern.isTypedVar(targetNode) && compiledPattern.getHandler(targetNode).canMatch(targetNode, element) - ) { + compiledPattern.isTypedVar(targetNode) && compiledPattern.getHandler(targetNode).canMatch(targetNode, element)) { handler = compiledPattern.getHandler(targetNode); handler.setPinnedElement(element); elementToStartMatching = element; @@ -670,21 +672,21 @@ public class MatcherImpl { targetNode = targetNode.getParent(); if (options.isLooseMatching()) { - element = StructuralSearchUtil.getProfileByPsiElement(element).updateCurrentNode(element); - targetNode = StructuralSearchUtil.getProfileByPsiElement(element).updateCurrentNode(targetNode); + element = profile.updateCurrentNode(element); + targetNode = profile.updateCurrentNode(targetNode); } } - if (!(handler instanceof TopLevelMatchingHandler)) return null; + if (!(handler instanceof TopLevelMatchingHandler)) return Collections.emptyList(); } assert targetNode != null : "Could not match down up when no target node"; + System.out.println("elementToStartMatching = " + elementToStartMatching.getText()); match(elementToStartMatching); matchContext.getSink().matchingFinished(); - final int matchCount = sink.getMatches().size(); - assert matchCount <= 1; - return matchCount > 0 ? sink.getMatches().get(0) : null; + final List matches = sink.getMatches(); + return matches; } private class MatchOneVirtualFile extends MatchOneFile { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java index 8d102b0b2440..869451a6b202 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java @@ -77,14 +77,15 @@ public class XmlMatchingVisitor extends XmlElementVisitor { PsiElement[] matchedNodes = another.getValue().getChildren(); if (contentChildren.length != 1) { - patternNodes = expandXmlTexts(patternNodes); - matchedNodes = expandXmlTexts(matchedNodes); + patternNodes = filterOutWhitespace(patternNodes); + matchedNodes = filterOutWhitespace(matchedNodes); } - myMatchingVisitor.setResult(myMatchingVisitor.matchSequentially( + final boolean result = myMatchingVisitor.matchSequentially( new ArrayBackedNodeIterator(patternNodes), new ArrayBackedNodeIterator(matchedNodes) - )); + ); + myMatchingVisitor.setResult(result); } } @@ -97,34 +98,27 @@ public class XmlMatchingVisitor extends XmlElementVisitor { } } - private static PsiElement[] expandXmlTexts(PsiElement[] children) { + private static PsiElement[] filterOutWhitespace(PsiElement[] children) { final List result = new ArrayList(children.length); - for(PsiElement c:children) { - if (c instanceof XmlText) { - for(PsiElement p:c.getChildren()) { - if (!(p instanceof PsiWhiteSpace)) result.add(p); + for(PsiElement child : children) { + if (child instanceof XmlText) { + final PsiElement[] grandChildren = child.getChildren(); + if (grandChildren.length == 1 && grandChildren[0] instanceof PsiWhiteSpace) { + continue; } - } else if (!(c instanceof PsiWhiteSpace)) { - result.add(c); } + result.add(child); } return PsiUtilCore.toPsiElementArray(result); } @Override public void visitXmlText(XmlText text) { - myMatchingVisitor.setResult(myMatchingVisitor.matchSequentially(text.getFirstChild(), myMatchingVisitor.getElement().getFirstChild())); - } - - @Override public void visitXmlToken(XmlToken token) { - if (token.getTokenType() == XmlTokenType.XML_DATA_CHARACTERS) { - final String text = token.getText(); - final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(text); - - if (isTypedVar) { - myMatchingVisitor.setResult(myMatchingVisitor.handleTypedElement(token, myMatchingVisitor.getElement())); - } else { - myMatchingVisitor.setResult(matches(text, myMatchingVisitor.getElement().getText())); - } + final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(text); + final PsiElement element = myMatchingVisitor.getElement(); + if (isTypedVar) { + myMatchingVisitor.setResult(myMatchingVisitor.handleTypedElement(text, element)); + } else { + myMatchingVisitor.setResult(matches(text.getText(), element.getText())); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java index 07808d33c003..6a20da7294c9 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java @@ -466,7 +466,8 @@ public class PatternCompiler { ); if (!StringUtil.isEmptyOrSpaces(constraint.getWithinConstraint())) { - MatchPredicate predicate = new WithinPredicate(Configuration.CONTEXT_VAR_NAME, constraint.getWithinConstraint(), project); + MatchPredicate predicate = + new WithinPredicate(Configuration.CONTEXT_VAR_NAME, constraint.getWithinConstraint(), options.getFileType(), project); if (constraint.isInvertWithinConstraint()) { predicate = new NotPredicate(predicate); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java index 99917ad23240..529b9deab344 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java @@ -5,10 +5,10 @@ import com.intellij.psi.XmlRecursiveElementVisitor; import com.intellij.psi.xml.XmlTag; import com.intellij.psi.xml.XmlText; import com.intellij.psi.xml.XmlToken; +import com.intellij.structuralsearch.impl.matcher.CompiledPattern; import com.intellij.structuralsearch.impl.matcher.filters.TagValueFilter; import com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler; import com.intellij.structuralsearch.impl.matcher.handlers.TopLevelMatchingHandler; -import com.intellij.structuralsearch.impl.matcher.handlers.XmlTextHandler; import com.intellij.structuralsearch.impl.matcher.strategies.XmlMatchingStrategy; /** @@ -26,17 +26,15 @@ public class XmlCompilingVisitor extends XmlRecursiveElementVisitor { super.visitElement(element); } - @Override public void visitXmlToken(XmlToken token) { - super.visitXmlToken(token); + @Override + public void visitXmlToken(XmlToken token) {} - if (token.getParent() instanceof XmlText && myCompilingVisitor.getContext().getPattern().isRealTypedVar(token)) { - final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(token); - handler.setFilter(TagValueFilter.getInstance()); + @Override + public void visitXmlText(XmlText text) { + super.visitXmlText(text); - final XmlTextHandler parentHandler = new XmlTextHandler(); - myCompilingVisitor.getContext().getPattern().setHandler(token.getParent(), parentHandler); - parentHandler.setFilter(TagValueFilter.getInstance()); - } + final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(text); + handler.setFilter(TagValueFilter.getInstance()); } @Override public void visitXmlTag(XmlTag xmlTag) { @@ -45,9 +43,9 @@ public class XmlCompilingVisitor extends XmlRecursiveElementVisitor { myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() - 1); if (myCompilingVisitor.getCodeBlockLevel() == 1) { - myCompilingVisitor.getContext().getPattern().setStrategy(XmlMatchingStrategy.getInstance()); - myCompilingVisitor.getContext().getPattern() - .setHandler(xmlTag, new TopLevelMatchingHandler(myCompilingVisitor.getContext().getPattern().getHandler(xmlTag))); + final CompiledPattern pattern = myCompilingVisitor.getContext().getPattern(); + pattern.setStrategy(XmlMatchingStrategy.getInstance()); + pattern.setHandler(xmlTag, new TopLevelMatchingHandler(pattern.getHandler(xmlTag))); } } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java index 89c295ce1d80..e59447312ed7 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java @@ -1,7 +1,8 @@ package com.intellij.structuralsearch.impl.matcher.filters; +import com.intellij.psi.PsiErrorElement; +import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.XmlElementVisitor; -import com.intellij.psi.xml.XmlText; /** * @author Eugene.Kudelevsky @@ -13,7 +14,13 @@ public class XmlLexicalNodesFilter extends XmlElementVisitor { this.myLexicalNodesFilter = lexicalNodesFilter; } - @Override public void visitXmlText(XmlText text) { + @Override + public void visitWhiteSpace(PsiWhiteSpace space) { + myLexicalNodesFilter.setResult(true); + } + + @Override + public void visitErrorElement(PsiErrorElement element) { myLexicalNodesFilter.setResult(true); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java index 3904eb397bce..fc7984680db9 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java @@ -1,14 +1,18 @@ package com.intellij.structuralsearch.impl.matcher.predicates; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.structuralsearch.MatchOptions; import com.intellij.structuralsearch.MatchResult; import com.intellij.structuralsearch.Matcher; import com.intellij.structuralsearch.impl.matcher.MatchContext; import com.intellij.structuralsearch.impl.matcher.compiler.PatternCompiler; +import java.util.List; + /** * @author Maxim.Mossienko */ @@ -16,11 +20,12 @@ public class WithinPredicate extends AbstractStringBasedPredicate { private final MatchOptions myMatchOptions; private Matcher matcher; - public WithinPredicate(String name, String within, Project project) { + public WithinPredicate(String name, String within, FileType fileType, Project project) { super(name, within); myMatchOptions = new MatchOptions(); myMatchOptions.setLooseMatching(true); + myMatchOptions.setFileType(fileType); final String unquoted = StringUtil.stripQuotesAroundValue(within); if (!unquoted.equals(within)) { myMatchOptions.setSearchPattern(unquoted); @@ -32,7 +37,12 @@ public class WithinPredicate extends AbstractStringBasedPredicate { } public boolean match(PsiElement node, PsiElement match, int start, int end, MatchContext context) { - final MatchResult result = matcher.isMatchedByDownUp(match, myMatchOptions); - return result != null; + final List results = matcher.matchByDownUp(match, myMatchOptions); + for (MatchResult result : results) { + if (PsiTreeUtil.isAncestor(result.getMatch(), match, false)) { + return true; + } + } + return false; } } \ No newline at end of file diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java index 258aaf6b8ccc..9a137efee3a1 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java @@ -48,8 +48,8 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Collection; import java.util.List; -import java.util.Set; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -226,10 +226,10 @@ class EditVarConstraintsDialog extends DialogWrapper { customScriptCode.getButton().addActionListener(new ActionListener() { public void actionPerformed(@NotNull final ActionEvent e) { - Set strings = ContainerUtil.collectSet(model.getConfig().getMatchOptions().getVariableConstraintNames()); - strings.remove(current.getName()); - strings.remove(CompiledPattern.ALL_CLASS_UNMATCHED_CONTENT_VAR_ARTIFICIAL_NAME); - EditScriptDialog dialog = new EditScriptDialog(project, customScriptCode.getChildComponent().getText(), strings); + final List variableNames = ContainerUtil.newArrayList(model.getConfig().getMatchOptions().getVariableConstraintNames()); + variableNames.remove(current.getName()); + variableNames.remove(CompiledPattern.ALL_CLASS_UNMATCHED_CONTENT_VAR_ARTIFICIAL_NAME); + final EditScriptDialog dialog = new EditScriptDialog(project, customScriptCode.getChildComponent().getText(), variableNames); dialog.show(); if (dialog.getExitCode() == OK_EXIT_CODE) { customScriptCode.getChildComponent().setText(dialog.getScriptText()); @@ -423,13 +423,11 @@ class EditVarConstraintsDialog extends DialogWrapper { invertWithinIn.setSelected(varInfo.isInvertWithinConstraint()); } - boolean isExprContext = true; final boolean contextVar = Configuration.CONTEXT_VAR_NAME.equals(var.getName()); - if (contextVar) isExprContext = false; containedInConstraints.setVisible(contextVar); - expressionConstraints.setVisible(isExprContext); - partOfSearchResults.setEnabled(!contextVar); //? - + textConstraintsPanel.setVisible(!contextVar); + expressionConstraints.setVisible(!contextVar); + partOfSearchResults.setVisible(!contextVar); occurencePanel.setVisible(!contextVar); } @@ -439,7 +437,6 @@ class EditVarConstraintsDialog extends DialogWrapper { expressionConstraints.setVisible(b); partOfSearchResults.setVisible(b); containedInConstraints.setVisible(b); - pack(); } private void restoreScriptCode(NamedScriptableDefinition varInfo) { @@ -593,7 +590,7 @@ class EditVarConstraintsDialog extends DialogWrapper { private final Editor editor; private final String title; - public EditScriptDialog(Project project, String text, Set names) { + public EditScriptDialog(Project project, String text, Collection names) { super(project, true); setTitle(SSRBundle.message("edit.groovy.script.constraint.title")); editor = createEditor(project, text, "1.groovy"); @@ -612,13 +609,10 @@ class EditVarConstraintsDialog extends DialogWrapper { } protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new BorderLayout()); + final JPanel panel = new JPanel(new BorderLayout()); panel.add(editor.getComponent(), BorderLayout.CENTER); if (!title.isEmpty()) { - JTextField f=new JTextField(title); - f.setEditable(false); - f.setBorder(null); - panel.add(f, BorderLayout.SOUTH); + panel.add(new JLabel(title), BorderLayout.SOUTH); } return panel; } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java index 0720cac36c20..4fe8b7d2201d 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java @@ -436,11 +436,9 @@ public class SearchDialog extends DialogWrapper { ); model.getConfig().getMatchOptions().clearVariableConstraints(); - if (matchOptions.hasVariableConstraints()) { - for (Iterator i = matchOptions.getVariableConstraintNames(); i.hasNext(); ) { - final MatchVariableConstraint constraint = (MatchVariableConstraint)matchOptions.getVariableConstraint(i.next()).clone(); - model.getConfig().getMatchOptions().addVariableConstraint(constraint); - } + for (String name : matchOptions.getVariableConstraintNames()) { + final MatchVariableConstraint constraint = (MatchVariableConstraint)matchOptions.getVariableConstraint(name).clone(); + model.getConfig().getMatchOptions().addVariableConstraint(constraint); } MatchOptions options = configuration.getMatchOptions(); @@ -829,6 +827,7 @@ public class SearchDialog extends DialogWrapper { for (Variable variable : variables) { variableNames.add(variable.getName()); } + variableNames.add(Configuration.CONTEXT_VAR_NAME); configuration.getMatchOptions().retainVariableConstraints(variableNames); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form index 20094b213e64..d57ceb3fd293 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form @@ -1,6 +1,6 @@
- + @@ -11,7 +11,11 @@ - + + + + + @@ -19,30 +23,20 @@ - - + - + + + - - - - - - - - - - - - + - + @@ -95,7 +89,7 @@ - + @@ -203,7 +197,7 @@ - + @@ -211,52 +205,13 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -315,7 +270,7 @@ - + @@ -341,10 +296,39 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java index ff2083ebfbfa..5ea22da14d3b 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java @@ -1,6 +1,7 @@ package com.intellij.structuralsearch; import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.structuralsearch.inspection.highlightTemplate.SSBasedInspection; import com.intellij.structuralsearch.plugin.ui.Configuration; import com.intellij.structuralsearch.plugin.ui.SearchConfiguration; @@ -20,11 +21,13 @@ public class SSBasedInspectionTest extends InspectionTestCase { List configurations = new ArrayList(); SearchConfiguration configuration = new SearchConfiguration(); MatchOptions options = new MatchOptions(); + options.setFileType(StdFileTypes.JAVA); options.setSearchPattern("int i;"); configuration.setMatchOptions(options); configurations.add(configuration); configuration = new SearchConfiguration(); options = new MatchOptions(); + options.setFileType(StdFileTypes.JAVA); options.setSearchPattern("f();"); configuration.setMatchOptions(options); configurations.add(configuration); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java index 95cd33b0845a..2f9bf669def3 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java @@ -1,5 +1,6 @@ package com.intellij.structuralsearch; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.structuralsearch.inspection.highlightTemplate.SSBasedInspection; import com.intellij.structuralsearch.plugin.ui.Configuration; import com.intellij.structuralsearch.plugin.ui.SearchConfiguration; @@ -60,6 +61,7 @@ public class SSRCodeInsightTest extends UsefulTestCase { //search pattern final MatchOptions options = new MatchOptions(); + options.setFileType(StdFileTypes.JAVA); options.setSearchPattern(searchPattern); configuration.setMatchOptions(options); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index 54be5b887f9d..a8d846767a86 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -1,5 +1,6 @@ package com.intellij.structuralsearch; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.CommonClassNames; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.util.ThrowableRunnable; @@ -12,6 +13,13 @@ import java.io.IOException; */ @SuppressWarnings({"ALL"}) public class StructuralReplaceTest extends StructuralReplaceTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + options.getMatchOptions().setFileType(StdFileTypes.JAVA); + } + public void testReplaceInLiterals() { String s1 = "String ID_SPEED = \"Speed\";"; String s2 = "String 'name = \"'string\";"; @@ -449,7 +457,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { actualResult ); - /*String s55 = "for(Iterator iterator = stringlist.iterator(); iterator.hasNext();) {\n" + + String s55 = "for(Iterator iterator = stringlist.iterator(); iterator.hasNext();) {\n" + " String str = iterator.next();\n" + " System.out.println( str );\n" + "}"; @@ -460,7 +468,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String s57 = "for($Type$ $var$:$container$) {\n" + " $Statements$;\n" + "}"; - String expectedResult20 = "for(String str :stringlist) {\n" + + String expectedResult20 = "for(String str:stringlist) {\n" + " System.out.println( str );\n" + "}"; @@ -470,7 +478,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "for with foreach", expectedResult20, actualResult - );*/ + ); String s58 = "class A {\n" + " static Set b_MAP = new HashSet();\n" + diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 732859261018..ef53d82b13ed 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -1,6 +1,5 @@ package com.intellij.structuralsearch; -import com.intellij.idea.Bombed; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.*; import com.intellij.structuralsearch.impl.matcher.MatcherImplUtil; @@ -9,7 +8,6 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; /** @@ -842,6 +840,18 @@ public class StructuralSearchTest extends StructuralSearchTestCase { "return !(x);"; String s10034 = "return ('a);"; assertEquals("Find statement with parenthesized expr",2,findMatchesCount(s10033,s10034)); + + String in = "if (true) {" + + " System.out.println();" + + "} else {" + + " System.out.println();" + + "}" + + "if (true) System.out.println();"; + String pattern1 = "if ('_exp) { '_statement*; }"; + assertEquals("Find if statement with else", 2, findMatchesCount(in, pattern1)); + + String pattern2 = "if ('_exp) { '_statement*; } else { '_statement2{0,0}; }"; + assertEquals("Find if statement without else", 1, findMatchesCount(in, pattern2)); } public void testSearchClass() { @@ -2728,12 +2738,10 @@ public class StructuralSearchTest extends StructuralSearchTestCase { options.setFileType(StdFileTypes.JAVA); for(PsiVariable var:vars) { - final MatchResult matchResult = testMatcher.isMatchedByDownUp(var, options); - if (matchResult != null) results.add(matchResult); - assertTrue( - (var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && matchResult != null) || - matchResult == null - ); + final List matchResult = testMatcher.matchByDownUp(var, options); + results.addAll(matchResult); + assertTrue((var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && !matchResult.isEmpty()) || + matchResult.isEmpty()); } assertEquals(2, results.size()); @@ -2752,12 +2760,10 @@ public class StructuralSearchTest extends StructuralSearchTestCase { for(PsiVariable var:vars) { final PsiTypeElement typeElement = var.getTypeElement(); - final MatchResult matchResult = testMatcher.isMatchedByDownUp(typeElement, options); - if (matchResult != null) results.add(matchResult); - assertTrue( - (var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && matchResult != null) || - matchResult == null - ); + final List matchResult = testMatcher.matchByDownUp(typeElement, options); + results.addAll(matchResult); + assertTrue((var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && !matchResult.isEmpty()) || + matchResult.isEmpty()); } assertEquals(1, results.size()); @@ -2766,7 +2772,6 @@ public class StructuralSearchTest extends StructuralSearchTestCase { assertEquals("Type2", result.getMatchImage()); } - @Bombed(day = 28, description = "support it", month = Calendar.JULY, user = "maxim.mossienko") public void _testContainsPredicate() { String s1 = "{{\n" + " int a;\n" + @@ -2808,35 +2813,43 @@ public class StructuralSearchTest extends StructuralSearchTestCase { assertEquals(2,findMatchesCount(s1, s2)); assertEquals(1,findMatchesCount(s1, s2_2)); - // TODO: xxx - //String s3 = "if (true) {\n" + - // " if (true) return;\n" + - // " int a = 1;\n" + - // "}\n else if (true) {\n" + - // " return;\n" + - // "}"; - //assertEquals(2,findMatchesCount(s3, s2)); - //assertEquals(1,findMatchesCount(s3, s2_2)); + String s3 = "if (true) {\n" + + " if (true) return;\n" + + " int a = 1;\n" + + "}\n" + + "else if (true) {\n" + + " int b = 2;\n" + + " return;\n" + + "}\n" + + "int c = 3;\n"; + assertEquals(2,findMatchesCount(s3, s2)); + assertEquals(1,findMatchesCount(s3, s2_2)); } public void testWithinPredicate2() { String s3 = "class C {\n" + " void aaa() {\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + + " LOG.debug(1);\n" + + " LOG.debug(2);\n" + + " LOG.debug(3);\n" + + " LOG.debug(4);\n" + + " LOG.debug(5);\n" + " if (true) {\n" + - " LOG.debug(true);\n" + + " LOG.debug(6);\n" + " }\n" + - " if (true) LOG.debug(true);\n" + - " if (true) { int 1 = 1; } else { LOG.debug(true); }\n" + + " if (true) LOG.debug(7);\n" + + " if (true) { int 1 = 1; } else { LOG.debug(8); }\n" + + " if (true) {\n" + + " if (true) {}\n" + + " if (true) {}\n" + + " } else{\n" + + " LOG.debug(9);\n" + + " }" + " }" + "}"; String s4 = "LOG.debug('_params*:[!within( \"if('_a) { 'st*; }\" )]);"; - assertEquals(6,findMatchesCount(s3, s4)); + assertEquals(7,findMatchesCount(s3, s4)); } public void testMultiStatementPatternWithTypedVariable() throws Exception { diff --git a/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java b/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java index 370465f3f994..967beebc2078 100644 --- a/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java +++ b/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java @@ -5,17 +5,18 @@ import com.intellij.openapi.options.*; import org.jetbrains.annotations.NotNull; public class MockSchemesManagerFactory extends SchemesManagerFactory { + private static final SchemesManager EMPTY = new EmptySchemesManager(); + @NotNull @Override public SchemesManager createSchemesManager(@NotNull String fileSpec, @NotNull SchemeProcessor processor, @NotNull RoamingType roamingType) { //noinspection unchecked - return SchemesManager.EMPTY; + return EMPTY; } @Override public void updateConfigFilesFromStreamProviders() { - } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index c4f1f70276e6..114892b0266e 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -159,6 +159,8 @@ ide.mac.boldEditorTabs=false ide.mac.disableMacScrollbars=false ide.mac.disableMacScrollbars.restartRequired=true ide.mac.disableMacScrollbars.description=Disables OS X overlay scrollbars +ide.mac.pressAndHold.workaround=true +ide.mac.pressAndHold.workaround.description=Enable workaround for press-and-hold input method for accented characters on Mac OS ide.perProjectModality=false ide.perProjectModality.description=New modality approach. All dialogs are DOCUMENT_MODAL expect ide-wide dialogs @@ -257,6 +259,9 @@ java.annotations.inference.nullable.method.description=Restart is required; infe java.annotations.inference.nullable.method.transitivity=true java.annotations.inference.nullable.method.transitivity.description=Restart is required; if a method result is a call to a @Nullable method, reports the caller as @Nullable as well +java.correct.class.type.by.place.resolve.scope=true +java.correct.class.type.by.place.resolve.scope.description=When resolving Java references, use the resolve scope of the currently processed source file + documentation.component.editor.font=false ide.completion.show.better.matching.classes=true @@ -540,3 +545,5 @@ git.status.write=true cidr.cygwin.cmakePermissionsFix=true cidr.cygwin.cmakePermissionsFix.description=Update permissions for the bin/ folder inside the installed IDE so that the bundled CMake could run +cidr.lldb.enableXcodeLLDB=false +cidr.lldb.enableXcodeLLDB.description=Enable LLDB from Xcode diff --git a/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java b/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java index b38c827adf9f..29f1cfaa7c6c 100644 --- a/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java +++ b/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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,15 +16,16 @@ package com.intellij.openapi.diff.impl; import com.intellij.CommonBundle; -import com.intellij.openapi.diff.impl.string.DiffString; import com.intellij.openapi.diff.ex.DiffFragment; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.highlighting.Util; import com.intellij.openapi.diff.impl.processing.DiffCorrection; import com.intellij.openapi.diff.impl.processing.Formatting; import com.intellij.openapi.diff.impl.processing.Word; +import com.intellij.openapi.diff.impl.string.DiffString; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.diff.Diff; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; @@ -241,8 +242,7 @@ public abstract class ComparisonPolicy { if (fragment.isOneSide()) { FragmentSide side = FragmentSide.chooseSide(fragment); DiffString text = side.getText(fragment); - DiffString trimed = text.trim(); - if (trimed.isEmpty()) { + if (StringUtil.isEmptyOrSpaces(text)) { collector.add(side.createFragment(text, DiffString.EMPTY, false)); return; } diff --git a/platform/util/src/com/intellij/openapi/project/IndexNotReadyException.java b/platform/util/src/com/intellij/openapi/project/IndexNotReadyException.java deleted file mode 100644 index 80ef38138b89..000000000000 --- a/platform/util/src/com/intellij/openapi/project/IndexNotReadyException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2000-2013 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.project; - -/** - * Thrown on accessing indices in dumb mode. Possible fixes: - *
  • if {@link com.intellij.openapi.actionSystem.AnAction#actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent)} is in stack trace, - * consider making the action not implement {@link com.intellij.openapi.project.DumbAware}. - *
  • if this access is performed from some invokeLater activity, consider replacing it with - * {@link com.intellij.openapi.project.DumbService#smartInvokeLater(Runnable)} - *
  • otherwise, add {@link DumbService#isDumb()} checks where necessary - * - * @author peter - * @see com.intellij.openapi.project.DumbService - * @see com.intellij.openapi.project.DumbAware - */ -public class IndexNotReadyException extends RuntimeException { - - @Override - public String getMessage() { - return "Please change caller according to " + IndexNotReadyException.class.getName() + " documentation"; - } -} diff --git a/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java b/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java index bf98c0f63b6d..65a7ee3988a7 100644 --- a/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java +++ b/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java @@ -68,9 +68,6 @@ public class ZipFileCache { } } - private static final boolean ourEnabled = - ZipFileCache.class.getClassLoader().getResource("com/intellij/openapi/application/Application.class") != null; - private static final Object ourLock = new Object(); private static final Map ourPathCache = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY); private static final Map ourFileCache = ContainerUtil.newHashMap(); @@ -79,29 +76,20 @@ public class ZipFileCache { private static final ScheduledThreadPoolExecutor ourExecutor; static { - if (ourEnabled) { - ourExecutor = ConcurrencyUtil.newSingleScheduledThreadExecutor("ZipFileCache Dispose", Thread.MIN_PRIORITY); - ourExecutor.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - List toClose = getFilesToClose(0, System.currentTimeMillis() - TIMEOUT); - if (toClose != null) { - close(toClose); - } + ourExecutor = ConcurrencyUtil.newSingleScheduledThreadExecutor("ZipFileCache Dispose", Thread.MIN_PRIORITY); + ourExecutor.scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + List toClose = getFilesToClose(0, System.currentTimeMillis() - TIMEOUT); + if (toClose != null) { + close(toClose); } - }, PERIOD, PERIOD, TimeUnit.MILLISECONDS); - } - else { - ourExecutor = null; - } + } + }, PERIOD, PERIOD, TimeUnit.MILLISECONDS); } @NotNull public static ZipFile acquire(@NotNull String path) throws IOException { - if (!ourEnabled) { - return new ZipFile(path); - } - path = FileUtil.toCanonicalPath(path); synchronized (ourLock) { @@ -178,11 +166,6 @@ public class ZipFileCache { } public static void release(@NotNull ZipFile file) { - if (!ourEnabled) { - close(file); - return; - } - synchronized (ourLock) { CacheRecord record = ourFileCache.get(file); if (record != null) { diff --git a/platform/util/src/com/intellij/openapi/util/registry/Registry.java b/platform/util/src/com/intellij/openapi/util/registry/Registry.java index dcf20c7def7c..32e2e4fe7f13 100644 --- a/platform/util/src/com/intellij/openapi/util/registry/Registry.java +++ b/platform/util/src/com/intellij/openapi/util/registry/Registry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -35,7 +35,6 @@ public class Registry { public static final String REGISTRY_BUNDLE = "misc.registry"; private final Map myUserProperties = new LinkedHashMap(); - private final Map myLoadedUserProperties = new HashMap(); private final Map myValues = new ConcurrentHashMap(); private static final Registry ourInstance = new Registry(); @@ -119,20 +118,18 @@ public class Registry { } public void loadState(@NotNull Element state) { - final List entries = state.getChildren("entry"); - for (Object each : entries) { - final Element eachEntry = (Element) each; - final String eachKey = eachEntry.getAttributeValue("key"); - final String eachValue = eachEntry.getAttributeValue("value"); - if (eachKey != null && eachValue != null) { - myUserProperties.put(eachKey, eachValue); + myUserProperties.clear(); + for (Element eachEntry : state.getChildren("entry")) { + String key = eachEntry.getAttributeValue("key"); + String value = eachEntry.getAttributeValue("value"); + if (key != null && value != null) { + RegistryValue registryValue = get(key); + if (registryValue.isChangedFromDefault(value)) { + myUserProperties.put(key, value); + registryValue.resetCache(); + } } } - myLoadedUserProperties.putAll(myUserProperties); - - for (RegistryValue each : myValues.values()) { - each.resetCache(); - } } @NotNull @@ -165,11 +162,11 @@ public class Registry { } public boolean isInDefaultState() { - return getUserProperties().isEmpty(); + return myUserProperties.isEmpty(); } public boolean isRestartNeeded() { - return isRestartNeeded(myUserProperties) || isRestartNeeded(myLoadedUserProperties); + return isRestartNeeded(myUserProperties); } private static boolean isRestartNeeded(@NotNull Map map) { diff --git a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java index 22e6214530cf..96ddb5330f1f 100644 --- a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java +++ b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -109,7 +109,11 @@ public class RegistryValue { } public boolean isChangedFromDefault() { - return !asString().equals(getBundleValue(myKey, false)); + return isChangedFromDefault(asString()); + } + + boolean isChangedFromDefault(@NotNull String newValue) { + return !newValue.equals(getBundleValue(myKey, false)); } private String get(@NotNull String key, String defaultValue, boolean isValue) throws MissingResourceException { diff --git a/platform/util/src/com/intellij/util/ImageLoader.java b/platform/util/src/com/intellij/util/ImageLoader.java index 1fcc08ea333b..b8ac405c97f3 100644 --- a/platform/util/src/com/intellij/util/ImageLoader.java +++ b/platform/util/src/com/intellij/util/ImageLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -30,6 +30,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; @@ -63,7 +65,14 @@ public class ImageLoader implements Serializable { public static Image loadFromUrl(@NotNull URL url) { for (Pair each : getFileNames(url.toString())) { try { - return loadFromStream(URLUtil.openStream(new URL(each.first)), each.second); + Image image = loadFromStream(URLUtil.openStream(new URL(each.first)), each.second); + + //we can't check all 3rd party plugins and convince the authors to add @2x icons. + // isHiDPI() != isRetina() => we should scale images manually + if (image != null && JBUI.isHiDPI() && !each.first.contains("@2x")) { + image = upscale(image); + } + return image; } catch (IOException ignore) { } @@ -71,6 +80,19 @@ public class ImageLoader implements Serializable { return null; } + @NotNull + private static Image upscale(Image image) { + float scale = JBUI.scale(1f); + int width = (int)(scale * image.getWidth(null)); + int height = (int)(scale * image.getHeight(null)); + @SuppressWarnings("UndesirableClassUsage") + BufferedImage tmp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = tmp.createGraphics(); + g.drawImage(image, AffineTransform.getScaleInstance(scale, scale), null); + image = tmp; + return image; + } + @Nullable public static Image loadFromUrl(URL url, boolean dark, boolean retina) { for (Pair each : getFileNames(url.toString(), dark, retina || JBUI.isHiDPI())) { diff --git a/platform/util/src/com/intellij/util/SystemProperties.java b/platform/util/src/com/intellij/util/SystemProperties.java index 7929dd1ff629..14b6999cb868 100644 --- a/platform/util/src/com/intellij/util/SystemProperties.java +++ b/platform/util/src/com/intellij/util/SystemProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -135,4 +135,12 @@ public class SystemProperties { public static String getJavaVendor() { return System.getProperty("java.vendor"); } + + public static boolean is(String key) { + return getBooleanProperty(key, false); + } + + public static boolean has(String key) { + return System.getProperty(key) != null; + } } diff --git a/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java b/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java index cfe57a2aedaf..11e953de6dcf 100644 --- a/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java +++ b/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java @@ -96,7 +96,7 @@ public class MostlySingularMultiMap implements Serializable { return processValue(p, myMap.get(key)); } - private boolean processValue(@NotNull Processor p, Object v) { + private boolean processValue(@NotNull Processor p, Object v) { if (v instanceof Object[]) { for (Object o : (Object[])v) { if (!p.process((V)o)) return false; @@ -109,7 +109,7 @@ public class MostlySingularMultiMap implements Serializable { return true; } - public boolean processAllValues(@NotNull Processor p) { + public boolean processAllValues(@NotNull Processor p) { for (Object v : myMap.values()) { if (!processValue(p, v)) return false; } diff --git a/platform/util/src/com/intellij/util/lang/JarLoader.java b/platform/util/src/com/intellij/util/lang/JarLoader.java index 9c1fa395e6af..4a040e53ef88 100644 --- a/platform/util/src/com/intellij/util/lang/JarLoader.java +++ b/platform/util/src/com/intellij/util/lang/JarLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -64,7 +64,7 @@ class JarLoader extends Loader { if (myCanLockJar) { ZipFileCache.release(zipFile); } - else if (zipFile != null) { + else { zipFile.close(); } } @@ -72,21 +72,21 @@ class JarLoader extends Loader { @NotNull @Override public ClasspathCache.LoaderData buildData() throws IOException { - ClasspathCache.LoaderData loaderData = new ClasspathCache.LoaderData(); ZipFile zipFile = acquireZipFile(); try { + ClasspathCache.LoaderData loaderData = new ClasspathCache.LoaderData(); Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { - ZipEntry zipEntry = entries.nextElement(); - String name = zipEntry.getName(); + ZipEntry entry = entries.nextElement(); + String name = entry.getName(); loaderData.addResourceEntry(name); loaderData.addNameEntry(name); } + return loaderData; } finally { releaseZipFile(zipFile); } - return loaderData; } @Override @@ -99,15 +99,15 @@ class JarLoader extends Loader { } try { - ZipFile file = acquireZipFile(); + ZipFile zipFile = acquireZipFile(); try { - ZipEntry entry = file.getEntry(name); + ZipEntry entry = zipFile.getEntry(name); if (entry != null) { - return MemoryResource.load(getBaseURL(), file, entry); + return MemoryResource.load(getBaseURL(), zipFile, entry); } } finally { - releaseZipFile(file); + releaseZipFile(zipFile); } } catch (Exception e) { diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 0c80b543d838..70f4539f958a 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -17,6 +17,7 @@ package com.intellij.util.ui; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.border.CustomLineBorder; +import com.intellij.util.SystemProperties; import javax.swing.*; import javax.swing.border.Border; @@ -26,7 +27,27 @@ import java.awt.*; * @author Konstantin Bulenkov */ public class JBUI { - private static boolean IS_HIDPI = !SystemInfo.isMac && ("true".equals(System.getProperty("hidpi")) || "true".equals(System.getProperty("is.hidpi"))); + private static boolean IS_HIDPI = calculateHiDPI(); + + private static boolean calculateHiDPI() { + if (SystemInfo.isMac) { + return false; + } + + if (SystemProperties.is("hidpi")) { + return true; + } + + if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) { + return false; + } + + if (SystemInfo.isWindows && getSystemDPI() > 144) { + return true; + } + + return false; + } private static int getSystemDPI() { try { diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 3a8b93a92b11..566625c7378b 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1773,8 +1773,8 @@ public class UIUtil { } private static int THEME_BASED_TEXT_LCD_CONTRAST = 0; - private static int BEST_DARK_LCD_CONTRAST = 100; - private static int BEST_LIGHT_LCD_CONTRAST = 200; + private static int BEST_DARK_LCD_CONTRAST = 250; + private static int BEST_LIGHT_LCD_CONTRAST = 100; public static void setHintingForLCDText(Graphics2D g2d) { diff --git a/platform/util/src/com/intellij/util/xmlb/Accessor.java b/platform/util/src/com/intellij/util/xmlb/Accessor.java index 7e364b9b6105..90cedb02a8d5 100644 --- a/platform/util/src/com/intellij/util/xmlb/Accessor.java +++ b/platform/util/src/com/intellij/util/xmlb/Accessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -25,13 +25,6 @@ public interface Accessor { void write(Object o, Object value); - @Deprecated - @NotNull - /** - * @deprecated to remove in IDEA 15 - */ - Annotation[] getAnnotations(); - T getAnnotation(@NotNull Class annotationClass); String getName(); diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index 884b7e2aa656..3995cafbc9f1 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ReflectionUtil; +import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.MultiMap; @@ -39,7 +40,7 @@ import java.util.*; import java.util.List; class BeanBinding extends Binding { - private static final Logger LOG = Logger.getInstance(BeanBinding.class); + static final Logger LOG = Logger.getInstance(BeanBinding.class); private static final Map> ourAccessorCache = ContainerUtil.createConcurrentSoftValueMap(); @@ -47,7 +48,9 @@ class BeanBinding extends Binding { @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") private Binding[] myBindings; - private final Class myBeanClass; + final Class myBeanClass; + + ThreeState hasEqualMethod = ThreeState.UNSURE; public BeanBinding(@NotNull Class beanClass, @Nullable Accessor accessor) { super(accessor); @@ -86,7 +89,13 @@ class BeanBinding extends Binding { public Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter) { for (Binding binding : myBindings) { Accessor accessor = binding.getAccessor(); - if (!filter.accepts(accessor, o)) { + + if (filter instanceof SkipDefaultsSerializationFilter) { + if (((SkipDefaultsSerializationFilter)filter).equal(binding, o)) { + continue; + } + } + else if (!filter.accepts(accessor, o)) { continue; } @@ -121,6 +130,16 @@ class BeanBinding extends Binding { return instance; } + boolean equalByFields(@NotNull Object currentValue, @NotNull Object defaultValue, @NotNull SkipDefaultsSerializationFilter filter) { + for (Binding binding : myBindings) { + Accessor accessor = binding.getAccessor(); + if (!filter.equal(binding, accessor.read(currentValue), accessor.read(defaultValue))) { + return false; + } + } + return true; + } + @NotNull public TObjectFloatHashMap computeBindingWeights(@NotNull LinkedHashSet accessorNameTracker) { TObjectFloatHashMap weights = new TObjectFloatHashMap(accessorNameTracker.size()); diff --git a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java index c7fd18abad65..f2b0987aa0ca 100644 --- a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import org.jetbrains.annotations.NonNls; @@ -39,7 +38,7 @@ class FieldAccessor implements Accessor { return myField.get(o); } catch (IllegalAccessException e) { - throw new XmlSerializationException("Reading "+myField, e); + throw new XmlSerializationException("Reading " + myField, e); } } @@ -52,16 +51,10 @@ class FieldAccessor implements Accessor { myField.set(o, XmlSerializerImpl.convert(value, type)); } catch (IllegalAccessException e) { - throw new XmlSerializationException("Writing "+myField,e); + throw new XmlSerializationException("Writing " + myField, e); } } - @NotNull - @Override - public Annotation[] getAnnotations() { - return myField.getAnnotations(); - } - @Override public T getAnnotation(@NotNull Class annotationClass) { return myField.getAnnotation(annotationClass); diff --git a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java index 9780e683154d..3385dbc435ce 100644 --- a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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,8 +16,6 @@ package com.intellij.util.xmlb; -import com.intellij.util.SmartList; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -26,7 +24,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.List; class PropertyAccessor implements Accessor { private final String myName; @@ -80,15 +77,6 @@ class PropertyAccessor implements Accessor { } } - @Override - @NotNull - public Annotation[] getAnnotations() { - List result = new SmartList(); - ContainerUtil.addAll(result, myReadMethod.getAnnotations()); - ContainerUtil.addAll(result, myWriteMethod.getAnnotations()); - return result.toArray(new Annotation[result.size()]); - } - @Override public T getAnnotation(@NotNull Class annotationClass) { T annotation = myReadMethod.getAnnotation(annotationClass); diff --git a/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java index 01f6f68f4fd1..f12f3647952f 100644 --- a/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java +++ b/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,5 +18,5 @@ package com.intellij.util.xmlb; import org.jetbrains.annotations.NotNull; public interface SerializationFilter { - boolean accepts(@NotNull Accessor accessor, Object bean); + boolean accepts(@NotNull Accessor accessor, @NotNull Object bean); } diff --git a/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java b/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java index 7c1cb2b51795..6731bcaf7698 100644 --- a/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java +++ b/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,10 +20,7 @@ import org.jetbrains.annotations.Nullable; public abstract class SerializationFilterBase implements SerializationFilter { @Override - public final boolean accepts(@NotNull Accessor accessor, Object bean) { - if (bean == null) { - return true; - } + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accepts(accessor, bean, accessor.read(bean)); } diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java index f44785f6991c..559ad12f8dab 100644 --- a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java +++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import com.intellij.openapi.util.Comparing; @@ -31,7 +30,7 @@ public class SkipDefaultValuesSerializationFilters extends SerializationFilterBa @Override protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { - final Object defValue = accessor.read(getDefaultBean(bean)); + Object defValue = accessor.read(getDefaultBean(bean)); if (defValue instanceof Element && beanValue instanceof Element) { return !JDOMUtil.areElementsEqual((Element)beanValue, (Element)defValue); } @@ -40,7 +39,8 @@ public class SkipDefaultValuesSerializationFilters extends SerializationFilterBa } } - private Object getDefaultBean(@NotNull Object bean) { + @NotNull + Object getDefaultBean(@NotNull Object bean) { Class c = bean.getClass(); Object o = myDefaultBeans.get(c); if (o == null) { diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java new file mode 100644 index 000000000000..5d43f7c01d49 --- /dev/null +++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2015 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.xmlb; + +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.util.ThreeState; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class SkipDefaultsSerializationFilter extends SkipDefaultValuesSerializationFilters { + boolean equal(@NotNull Binding binding, @NotNull Object bean) { + Accessor accessor = binding.getAccessor(); + return equal(binding, accessor.read(bean), accessor.read(getDefaultBean(bean))); + } + + boolean equal(@Nullable Binding binding, @Nullable Object currentValue, @Nullable Object defaultValue) { + if (defaultValue instanceof Element && currentValue instanceof Element) { + return JDOMUtil.areElementsEqual((Element)currentValue, (Element)defaultValue); + } + else { + if (currentValue == defaultValue) { + return true; + } + if (currentValue == null || defaultValue == null) { + return false; + } + + if (binding instanceof BasePrimitiveBinding) { + Binding referencedBinding = ((BasePrimitiveBinding)binding).myBinding; + if (referencedBinding instanceof BeanBinding) { + BeanBinding classBinding = (BeanBinding)referencedBinding; + ThreeState compareByFields = classBinding.hasEqualMethod; + if (compareByFields == ThreeState.UNSURE) { + try { + classBinding.myBeanClass.getDeclaredMethod("equals", Object.class); + compareByFields = ThreeState.NO; + } + catch (NoSuchMethodException ignored) { + compareByFields = ThreeState.YES; + } + catch (Exception e) { + BeanBinding.LOG.warn(e); + } + + classBinding.hasEqualMethod = compareByFields; + } + + if (compareByFields == ThreeState.YES) { + return classBinding.equalByFields(currentValue, defaultValue, this); + } + } + } + + return Comparing.equal(currentValue, defaultValue); + } + } +} diff --git a/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java b/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java index f254f451fcd1..c3af4340bf41 100644 --- a/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java +++ b/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,6 @@ import com.intellij.util.ThreeState; import gnu.trove.TObjectFloatHashMap; import org.jdom.Element; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.LinkedHashSet; @@ -40,11 +39,11 @@ public final class SmartSerializer { } : new SkipDefaultValuesSerializationFilters() { @Override - protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { if (mySerializedAccessorNameTracker != null && mySerializedAccessorNameTracker.contains(accessor.getName())) { return true; } - return super.accepts(accessor, bean, beanValue); + return super.accepts(accessor, bean); } }; } diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java index 97e4a35276a5..41a3e86a5a43 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,7 +31,7 @@ import java.util.Set; public class XmlSerializer { private static final SerializationFilter TRUE_FILTER = new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return true; } }; diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java index d518b9c5828a..d318dc2f8cd4 100644 --- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java +++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -158,6 +158,13 @@ public class XmlSerializerTest extends TestCase { bean); } + public void testSubBeanSerializationAndSkipDefaults() { + BeanWithSubBean bean = new BeanWithSubBean(); + doSerializerTest( + "", + bean, new SkipDefaultsSerializationFilter()); + } + public void testNullFieldValue() { BeanWithPublicFields bean1 = new BeanWithPublicFields(); @@ -538,7 +545,7 @@ public class XmlSerializerTest extends TestCase { "", new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accessor.getName().startsWith("I"); } }); @@ -851,7 +858,7 @@ public class XmlSerializerTest extends TestCase { } public static class PropertyFilterTest implements SerializationFilter { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return !accessor.read(bean).equals("skip"); } } @@ -1195,10 +1202,10 @@ public class XmlSerializerTest extends TestCase { public void testConverterUsingSkipDefaultsFilters() { BeanWithConverter bean = new BeanWithConverter(); - doSerializerTest("", bean, new SkipDefaultValuesSerializationFilters()); + doSerializerTest("", bean, new SkipDefaultsSerializationFilter()); bean.foo = Ref.create("testValue"); - doSerializerTest("", bean, new SkipDefaultValuesSerializationFilters()); + doSerializerTest("", bean, new SkipDefaultsSerializationFilter()); bean.foo = Ref.create(); bean.bar = Ref.create("testValue2"); @@ -1237,7 +1244,7 @@ public class XmlSerializerTest extends TestCase { Bean2 bean = new Bean2(); bean.module = "module"; bean.ab = "ab"; - doSerializerTest("", bean, new SkipDefaultValuesSerializationFilters()); + doSerializerTest("", bean, new SkipDefaultsSerializationFilter()); checkSmartSerialization(new Bean2(), ""); checkSmartSerialization(new Bean2(), ""); @@ -1264,7 +1271,7 @@ public class XmlSerializerTest extends TestCase { " \n" + " \n" + " \n" + - "", bean, new SkipDefaultValuesSerializationFilters()); + "", bean, new SkipDefaultsSerializationFilter()); } private static void checkSmartSerialization(@NotNull Bean2 bean, @NotNull String serialized) throws IOException, JDOMException { diff --git a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java index 0e51740f4c48..f17109fe4353 100644 --- a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java +++ b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java @@ -55,10 +55,10 @@ public class PatchReader { this(patchContent, true); } - public PatchReader(CharSequence patchContent, boolean parseHunks) { + public PatchReader(CharSequence patchContent, boolean saveHunks) { myLines = LineTokenizer.tokenizeIntoList(patchContent, false); - myAdditionalInfoParser = new AdditionalInfoParser(!parseHunks); - myPatchContentParser = new PatchContentParser(parseHunks); + myAdditionalInfoParser = new AdditionalInfoParser(!saveHunks); + myPatchContentParser = new PatchContentParser(saveHunks); } public List readAllPatches() throws PatchSyntaxException { @@ -254,15 +254,15 @@ public class PatchReader { private static class PatchContentParser implements Parser { - private final boolean myParseHunks; + private final boolean mySaveHunks; private DiffFormat myDiffFormat = null; private final List myPatches; private boolean myDiffCommandLike; private boolean myIndexLike; - private PatchContentParser(boolean parseHunks) { - myParseHunks = parseHunks; + private PatchContentParser(boolean saveHunks) { + mySaveHunks = saveHunks; myPatches = new SmartList(); } @@ -303,7 +303,7 @@ public class PatchReader { } private TextFilePatch readPatch(String curLine, ListIterator iterator) throws PatchSyntaxException { - final TextFilePatch curPatch = new TextFilePatch(null); + final TextFilePatch curPatch = mySaveHunks ? new TextFilePatch(null) : new EmptyTextFilePatch(); extractFileName(curLine, curPatch, true, myDiffCommandLike && myIndexLike); if (! iterator.hasNext()) throw new PatchSyntaxException(iterator.previousIndex(), "Second file name expected"); @@ -314,7 +314,7 @@ public class PatchReader { } extractFileName(curLine, curPatch, false, myDiffCommandLike && myIndexLike); - while (myParseHunks && iterator.hasNext()) { + while (iterator.hasNext()) { PatchHunk hunk; if (myDiffFormat == DiffFormat.UNIFIED) { hunk = readNextHunkUnified(iterator); @@ -595,4 +595,37 @@ public class PatchReader { boolean testIsStart(final String start); void parse(final String start, final ListIterator iterator) throws PatchSyntaxException; } + + private static class EmptyTextFilePatch extends TextFilePatch { + private int myHunkCount = 0; + private boolean myNew; + private boolean myDeleted; + + EmptyTextFilePatch() { + super(null); + } + + @Override + public void addHunk(PatchHunk hunk) { + if (myHunkCount == 0) { + if (hunk.isNewContent()) { + myNew = true; + } + else if (hunk.isDeletedContent()) { + myDeleted = true; + } + } + myHunkCount++; + } + + @Override + public boolean isNewFile() { + return myHunkCount == 1 && myNew; + } + + @Override + public boolean isDeletedFile() { + return myHunkCount == 1 && myDeleted; + } + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java index ce6ca72ab996..8b95fbe92c8c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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,7 +16,6 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.impl.ComparisonPolicy; import com.intellij.openapi.diff.impl.external.DiffManagerImpl; import com.intellij.openapi.diff.impl.fragments.LineFragment; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; @@ -87,11 +86,10 @@ public class FragmentedDiffRequestFromChange { filePath.hardRefresh(); file = filePath.getVirtualFile(); } - final PreparedFragmentedContent preparedFragmentedContent = new PreparedFragmentedContent(myProject, fragmentedContent, + return new PreparedFragmentedContent(myProject, fragmentedContent, filePath.getName(), filePath.getFileType(), change.getBeforeRevision() == null ? null : change.getBeforeRevision().getRevisionNumber(), change.getAfterRevision() == null ? null : change.getAfterRevision().getRevisionNumber(), filePath, file); - return preparedFragmentedContent; } private static class RangesCalculator { @@ -138,12 +136,8 @@ public class FragmentedDiffRequestFromChange { } } - ComparisonPolicy comparisonPolicy = DiffManagerImpl.getInstanceEx().getComparisonPolicy(); - if (comparisonPolicy == null) { - comparisonPolicy = ComparisonPolicy.DEFAULT; - } - final TextCompareProcessor processor = new TextCompareProcessor(comparisonPolicy); - final List lineFragments = processor.process(myOldDocument.getText(), myDocument.getText()); + TextCompareProcessor processor = new TextCompareProcessor(DiffManagerImpl.getInstanceEx().getComparisonPolicy()); + List lineFragments = processor.process(myOldDocument.getText(), myDocument.getText()); myRanges = new ArrayList>(lineFragments.size()); for (LineFragment lineFragment : lineFragments) { if (!lineFragment.isEqual()) { @@ -174,7 +168,7 @@ public class FragmentedDiffRequestFromChange { } } - private int correctRangeEnd(final int end, final Document document) { + private static int correctRangeEnd(final int end, final Document document) { if (end == 0) return end; return "\n".equals(document.getText(new TextRange(end - 1, end))) ? end - 1 : end; } @@ -187,7 +181,7 @@ public class FragmentedDiffRequestFromChange { return myException; } - private Document documentFromRevision(final ContentRevision cr) throws VcsException { + private static Document documentFromRevision(final ContentRevision cr) throws VcsException { final Document oldDocument = new DocumentImpl(StringUtil.convertLineSeparators(notNullContentRevision(cr)),true); // todo !!! a question how to show line separators in diff etc // todo currently document doesn't allow to put \r as separator @@ -195,7 +189,7 @@ public class FragmentedDiffRequestFromChange { return oldDocument; } - private String notNullContentRevision(final ContentRevision cr) throws VcsException { + private static String notNullContentRevision(final ContentRevision cr) throws VcsException { if (cr == null) return ""; String content = cr.getContent(); return content == null ? "" : content; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index ab79d9af9be1..5f5aa460d640 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -399,23 +399,25 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C @NotNull public Selection getSelection() { - return new Selection(); + return new Selection(this); } - public class Selection { + public static class Selection { private final TIntHashSet myCommits; + private final VcsLogGraphTable myTable; - public Selection() { - myCommits = getCommitsAtRows(myDataPack.getVisibleGraph(), getSelectedRows()); + public Selection(@NotNull VcsLogGraphTable table) { + myTable = table; + myCommits = getCommitsAtRows(myTable.myDataPack.getVisibleGraph(), myTable.getSelectedRows()); } public void restore(@NotNull VisibleGraph newVisibleGraph) { - TIntHashSet rowsToSelect = findNewRowsToSelect(getGraphTableModel(), newVisibleGraph, myCommits); + TIntHashSet rowsToSelect = findNewRowsToSelect(myTable.getGraphTableModel(), newVisibleGraph, myCommits); if (!rowsToSelect.isEmpty()) { rowsToSelect.forEach(new TIntProcedure() { @Override public boolean execute(int row) { - addRowSelectionInterval(row, row); + myTable.addRowSelectionInterval(row, row); return true; } }); diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java index ee949a2ae9ce..d7499346099f 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java @@ -30,6 +30,7 @@ import com.intellij.xdebugger.stepping.XSmartStepIntoHandler; import com.intellij.xdebugger.ui.XDebugTabLayouter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; import javax.swing.event.HyperlinkListener; @@ -131,7 +132,15 @@ public abstract class XDebugProcess { * Stop debugging and dispose resources. * Do not call this method directly. Use {@link XDebugSession#stop} instead */ - public abstract void stop(); + public void stop() { + throw new AbstractMethodError(); + } + + @NotNull + public Promise stopAsync() { + stop(); + return Promise.DONE; + } /** * Resume execution. diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 6b172c5432be..b8abd9764511 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -48,6 +48,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.AppUIUtil; +import com.intellij.util.Consumer; import com.intellij.util.EventDispatcher; import com.intellij.util.SmartList; import com.intellij.util.containers.SmartHashSet; @@ -110,7 +111,7 @@ public class XDebugSessionImpl implements XDebugSession { private final EventDispatcher myDispatcher = EventDispatcher.create(XDebugSessionListener.class); private final Project myProject; private final @Nullable ExecutionEnvironment myEnvironment; - private boolean myStopped; + private final AtomicBoolean myStopped = new AtomicBoolean(); private boolean myPauseActionSupported; private final AtomicBoolean myShowTabOnSuspend; private final List myRestartActions = new SmartList(); @@ -840,51 +841,56 @@ public class XDebugSessionImpl implements XDebugSession { @Override public boolean isStopped() { - return myStopped; + return myStopped.get(); } private void stopImpl() { - if (myStopped) return; - - myDebugProcess.stop(); - if (!myProject.isDisposed()) { - myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess); + if (!myStopped.compareAndSet(false, true)) { + return; } - if (mySessionTab != null) { - ((XWatchesViewImpl)mySessionTab.getWatchesView()).updateSessionData(); - mySessionTab.detachFromSession(); - } - else if (myConsoleView != null) { - Disposer.dispose(myConsoleView); - } + myDebugProcess.stopAsync().done(new Consumer() { + @Override + public void consume(Void aVoid) { + if (!myProject.isDisposed()) { + myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess); + } - myTopFramePosition = null; - myCurrentExecutionStack = null; - myCurrentStackFrame = null; - mySuspendContext = null; - if (myDebuggerManager.getCurrentSession() == this) { - myDebuggerManager.updateExecutionPoint(null, false, null); - } - if (breakpointsInitialized) { - XBreakpointManagerImpl breakpointManager = myDebuggerManager.getBreakpointManager(); - if (myBreakpointListener != null) { - breakpointManager.removeBreakpointListener(myBreakpointListener); + if (mySessionTab != null) { + ((XWatchesViewImpl)mySessionTab.getWatchesView()).updateSessionData(); + mySessionTab.detachFromSession(); + } + else if (myConsoleView != null) { + Disposer.dispose(myConsoleView); + } + + myTopFramePosition = null; + myCurrentExecutionStack = null; + myCurrentStackFrame = null; + mySuspendContext = null; + if (myDebuggerManager.getCurrentSession() == XDebugSessionImpl.this) { + myDebuggerManager.updateExecutionPoint(null, false, null); + } + if (breakpointsInitialized) { + XBreakpointManagerImpl breakpointManager = myDebuggerManager.getBreakpointManager(); + if (myBreakpointListener != null) { + breakpointManager.removeBreakpointListener(myBreakpointListener); + } + if (myDependentBreakpointListener != null) { + breakpointManager.getDependentBreakpointManager().removeListener(myDependentBreakpointListener); + } + } + if (myValueMarkers != null) { + myValueMarkers.clear(); + } + if (XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings().isUnmuteOnStop()) { + mySessionData.setBreakpointsMuted(false); + } + myDebuggerManager.removeSession(XDebugSessionImpl.this); + myDispatcher.getMulticaster().sessionStopped(); + myProject.putUserData(XDebuggerEditorLinePainter.CACHE, null); } - if (myDependentBreakpointListener != null) { - breakpointManager.getDependentBreakpointManager().removeListener(myDependentBreakpointListener); - } - } - if (myValueMarkers != null) { - myValueMarkers.clear(); - } - if (XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings().isUnmuteOnStop()) { - mySessionData.setBreakpointsMuted(false); - } - myStopped = true; - myDebuggerManager.removeSession(this); - myDispatcher.getMulticaster().sessionStopped(); - myProject.putUserData(XDebuggerEditorLinePainter.CACHE, null); + }); } public boolean isInactiveSlaveBreakpoint(final XBreakpoint breakpoint) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java index 64954449458b..1991167dca8f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java @@ -178,14 +178,12 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { return visitor.isIndexVariableUsedOnlyAsIndex(); } - static boolean isCollectionLoopStatement( - PsiForStatement forStatement, boolean ignoreUntypedCollections) { + static boolean isCollectionLoopStatement(PsiForStatement forStatement, boolean ignoreUntypedCollections) { final PsiStatement initialization = forStatement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return false; } - final PsiDeclarationStatement declaration = - (PsiDeclarationStatement)initialization; + final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); if (declaredElements.length != 1) { return false; @@ -195,9 +193,7 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { return false; } final PsiVariable variable = (PsiVariable)declaredElement; - if (!TypeUtils.variableHasTypeOrSubtype(variable, - CommonClassNames.JAVA_UTIL_ITERATOR, - "java.util.ListIterator")) { + if (!TypeUtils.variableHasTypeOrSubtype(variable, CommonClassNames.JAVA_UTIL_ITERATOR, "java.util.ListIterator")) { return false; } final PsiExpression initialValue = variable.getInitializer(); @@ -207,14 +203,10 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (!(initialValue instanceof PsiMethodCallExpression)) { return false; } - final PsiMethodCallExpression initialCall = - (PsiMethodCallExpression)initialValue; - final PsiReferenceExpression initialMethodExpression = - initialCall.getMethodExpression(); - @NonNls final String initialCallName = - initialMethodExpression.getReferenceName(); - if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName) && - !"listIterator".equals(initialCallName)) { + final PsiMethodCallExpression initialCall = (PsiMethodCallExpression)initialValue; + final PsiReferenceExpression initialMethodExpression = initialCall.getMethodExpression(); + @NonNls final String initialCallName = initialMethodExpression.getReferenceName(); + if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName) && !"listIterator".equals(initialCallName)) { return false; } final PsiExpressionList argumentList = initialCall.getArgumentList(); @@ -222,12 +214,10 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (arguments.length != 0) { return false; } - final PsiExpression qualifier = - initialMethodExpression.getQualifierExpression(); + final PsiExpression qualifier = initialMethodExpression.getQualifierExpression(); final PsiClass qualifierClass; if (qualifier == null) { - qualifierClass = - ClassUtils.getContainingClass(initialMethodExpression); + qualifierClass = ClassUtils.getContainingClass(initialMethodExpression); if (ignoreUntypedCollections) { final PsiClassType type = (PsiClassType)variable.getType(); final PsiType[] parameters = type.getParameters(); @@ -255,10 +245,8 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (qualifierClass == null) { return false; } - if (!InheritanceUtil.isInheritor(qualifierClass, - CommonClassNames.JAVA_LANG_ITERABLE) && - !InheritanceUtil.isInheritor(qualifierClass, - CommonClassNames.JAVA_UTIL_COLLECTION)) { + if (!InheritanceUtil.isInheritor(qualifierClass, CommonClassNames.JAVA_LANG_ITERABLE) && + !InheritanceUtil.isInheritor(qualifierClass, CommonClassNames.JAVA_UTIL_COLLECTION)) { return false; } final PsiExpression condition = forStatement.getCondition(); @@ -289,16 +277,13 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (body == null) { return 0; } - final NumCallsToIteratorNextVisitor visitor = - new NumCallsToIteratorNextVisitor(iterator); + final NumCallsToIteratorNextVisitor visitor = new NumCallsToIteratorNextVisitor(iterator); body.accept(visitor); return visitor.getNumCallsToIteratorNext(); } - private static boolean isIteratorMethodCalled(PsiVariable iterator, - PsiStatement body) { - final IteratorMethodCallVisitor visitor = - new IteratorMethodCallVisitor(iterator); + private static boolean isIteratorMethodCalled(PsiVariable iterator, PsiStatement body) { + final IteratorMethodCallVisitor visitor = new IteratorMethodCallVisitor(iterator); body.accept(visitor); return visitor.isMethodCalled(); } @@ -308,29 +293,25 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (!(condition instanceof PsiMethodCallExpression)) { return false; } - final PsiMethodCallExpression call = - (PsiMethodCallExpression)condition; + final PsiMethodCallExpression call = (PsiMethodCallExpression)condition; final PsiExpressionList argumentList = call.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 0) { return false; } - final PsiReferenceExpression methodExpression = - call.getMethodExpression(); + final PsiReferenceExpression methodExpression = call.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); if (!HardcodedMethodConstants.HAS_NEXT.equals(methodName)) { return false; } - final PsiExpression qualifier = - methodExpression.getQualifierExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (qualifier == null) { return true; } if (!(qualifier instanceof PsiReferenceExpression)) { return false; } - final PsiReferenceExpression referenceExpression = - (PsiReferenceExpression)qualifier; + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier; final PsiElement target = referenceExpression.resolve(); return iterator.equals(target); } @@ -636,31 +617,39 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { } @Override - public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression) { + public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { if (methodCalled) { return; } super.visitMethodCallExpression(expression); - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String name = methodExpression.getReferenceName(); if (HardcodedMethodConstants.NEXT.equals(name)) { return; } - final PsiExpression qualifier = - methodExpression.getQualifierExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiReferenceExpression)) { return; } - final PsiReferenceExpression referenceExpression = - (PsiReferenceExpression)qualifier; + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier; final PsiElement target = referenceExpression.resolve(); if (iterator.equals(target)) { methodCalled = true; } } + @Override + public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { + if (methodCalled) { + return; + } + super.visitMethodReferenceExpression(expression); + final PsiExpression qualifierExpression = expression.getQualifierExpression(); + if (qualifierExpression instanceof PsiReferenceExpression && iterator.equals(((PsiReferenceExpression)qualifierExpression).resolve())) { + methodCalled = true; + } + } + public boolean isMethodCalled() { return methodCalled; } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java index a6d67a938aaa..ee8a136d8ed6 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java @@ -45,9 +45,7 @@ public class SleepWhileHoldingLockInspection extends BaseInspection { return new SleepWhileHoldingLockVisitor(); } - private static class SleepWhileHoldingLockVisitor - extends BaseInspectionVisitor { - + private static class SleepWhileHoldingLockVisitor extends BaseInspectionVisitor { @Override public void visitMethodCallExpression( @NotNull PsiMethodCallExpression expression) { @@ -59,16 +57,14 @@ public class SleepWhileHoldingLockInspection extends BaseInspection { if (!"sleep".equals(methodName)) { return; } - final PsiMethod containingMethod = - PsiTreeUtil.getParentOfType(expression, PsiMethod.class); + final PsiMethod containingMethod = + PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class); boolean isSynced = false; - if (containingMethod != null && containingMethod - .hasModifierProperty(PsiModifier.SYNCHRONIZED)) { + if (containingMethod != null && containingMethod.hasModifierProperty(PsiModifier.SYNCHRONIZED)) { isSynced = true; } - final PsiSynchronizedStatement containingSyncStatement = - PsiTreeUtil.getParentOfType(expression, - PsiSynchronizedStatement.class); + final PsiSynchronizedStatement containingSyncStatement = + PsiTreeUtil.getParentOfType(expression, PsiSynchronizedStatement.class, true, PsiClass.class, PsiLambdaExpression.class); if (containingSyncStatement != null) { isSynced = true; } @@ -81,8 +77,7 @@ public class SleepWhileHoldingLockInspection extends BaseInspection { } final PsiClass methodClass = method.getContainingClass(); if (methodClass == null || - !InheritanceUtil.isInheritor(methodClass, - "java.lang.Thread")) { + !InheritanceUtil.isInheritor(methodClass, "java.lang.Thread")) { return; } registerMethodCallError(expression); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java index 28669193d19a..9961a7103f18 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java @@ -15,7 +15,6 @@ */ package com.siyeh.ig.style; -import com.intellij.codeInsight.javadoc.JavaDocUtil; import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.diagnostic.Logger; @@ -26,6 +25,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; +import com.intellij.psi.impl.source.codeStyle.ImportHelper; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; @@ -206,11 +206,6 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl if (element != null) { return; } - final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); - PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); - if (containingComment != null && acceptFullyQualifiedNamesInJavadoc(containingComment, styleSettings)) { - return; - } final PsiFile containingFile = reference.getContainingFile(); if (!(containingFile instanceof PsiJavaFile)) { return; @@ -219,6 +214,11 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl if (!(target instanceof PsiClass)) { return; } + final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); + PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); + if (containingComment != null && acceptFqnInJavadoc((PsiJavaFile)containingFile, reference.getQualifiedName(), styleSettings)) { + return; + } final PsiJavaCodeReferenceElement qualifierReference = (PsiJavaCodeReferenceElement)qualifier; final PsiElement qualifierTarget = qualifierReference.resolve(); if (!(qualifierTarget instanceof PsiPackage)) { @@ -262,11 +262,14 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl } } - public static boolean acceptFullyQualifiedNamesInJavadoc(PsiDocComment comment, CodeStyleSettings styleSettings) { - if (JavaDocUtil.isInsidePackageInfo(comment)) { + private static boolean acceptFqnInJavadoc(PsiJavaFile javaFile, String fullyQualifiedName, CodeStyleSettings styleSettings) { + if ("package-info.java".equals(javaFile.getName())) { return true; } JavaCodeStyleSettings javaSettings = styleSettings.getCustomSettings(JavaCodeStyleSettings.class); + if (javaSettings.CLASS_NAMES_IN_JAVADOC == JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED) { + return !ImportHelper.isAlreadyImported(javaFile, fullyQualifiedName); + } return javaSettings.useFqNamesInJavadocAlways(); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java index f742c291ad8a..eb06803e174a 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java @@ -273,6 +273,20 @@ public class ForCanBeForEach { } } } + + static class WithMethodRefs { + private static final List STRINGS = new ArrayList<>(Arrays.asList("Hello", "World")); + + public void test3() { + for (ListIterator stringListIterator = STRINGS.listIterator(); stringListIterator.hasNext(); ) { + System.out.println(stringListIterator.next()); + + List strings2 = new ArrayList<>(Collections.singletonList("!")); + + strings2.forEach(stringListIterator::add); + } + } + } } class OuterClass { diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java new file mode 100644 index 000000000000..de1e31544974 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java @@ -0,0 +1,7 @@ +import java.util.HashMap; + +/** + * {@link java.util.HashMap} + */ +public class DoubleQualify { +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java new file mode 100644 index 000000000000..193c25f043c5 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java @@ -0,0 +1,5 @@ +/** + * {@link java.util.HashMap} + */ +public class Single { +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml new file mode 100644 index 000000000000..05706352d657 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml @@ -0,0 +1,11 @@ + + + + + DoubleQualify.java + 4 + Unnecessary fully qualified name + Fully qualified name <code>java.util.HashMap</code> is unnecessary, and can be replaced with an import #loc + + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java index fe513136456d..71a0cb977274 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java @@ -1,7 +1,9 @@ package com.siyeh.ig.migration; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.testFramework.LightProjectDescriptor; import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.NotNull; public class ForCanBeForeachInspectionTest extends LightInspectionTestCase { @@ -18,4 +20,10 @@ public class ForCanBeForeachInspectionTest extends LightInspectionTestCase { protected String getBasePath() { return "/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach"; } + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_8; + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java index 8dc9ea7b861c..1856fc662a46 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java @@ -10,7 +10,7 @@ public class UnnecessaryFullyQualifiedNameInspectionTest extends IGInspectionTes private static final String BASE_DIR = "com/siyeh/igtest/style/"; public void testFqnInJavadoc_Unnecessary_WhenFullyQualifyIfNotImported() throws Exception { - doTestWithFqnInJavadocSetting(BASE_DIR + "unnecessary_fully_qualified_name/", JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED); + doTestWithFqnInJavadocSetting(BASE_DIR + "unnecessary_fqn_javadoc_fully_qualify_if_not_imported", JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED); } public void testFqnInJavadoc_Unnecessary_WhenShortNamesAlways() { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java index b2bfefce47e6..8db552b12ee6 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java @@ -76,6 +76,7 @@ public class Configuration extends SimpleModificationTracker implements Persiste @State( name = Configuration.COMPONENT_NAME, + defaultStateAsResource = true, storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/IntelliLang.xml", scheme = StorageScheme.DIRECTORY_BASED)}) public static class App extends Configuration { @@ -110,8 +111,10 @@ public class Configuration extends SimpleModificationTracker implements Persiste return getState(element); } } + @State( name = Configuration.COMPONENT_NAME, + defaultStateAsResource = true, storages = { @Storage(file = StoragePathMacros.PROJECT_FILE), @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/IntelliLang.xml", scheme = StorageScheme.DIRECTORY_BASED) diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java index 08748de5af2d..54205337eee4 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,7 +20,6 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.roots.ui.CellAppearanceEx; import com.intellij.openapi.roots.ui.FileAppearanceService; import com.intellij.openapi.roots.ui.ModifiableCellAppearanceEx; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -55,7 +54,7 @@ public class AllJarsUnderDirEntry implements AntClasspathEntry { this(new File(osPath)); } - public void writeExternal(final Element dataElement) throws WriteExternalException { + public void writeExternal(final Element dataElement) { String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, myDir.getAbsolutePath().replace(File.separatorChar, '/')); dataElement.setAttribute(DIR, url); } diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java index fb70c3728d9d..44931e324ebf 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,9 +18,7 @@ package com.intellij.lang.ant.config.impl; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.roots.ui.CellAppearanceEx; -import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.NullableFactory; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.PathUtil; @@ -35,23 +33,25 @@ import java.util.List; public interface AntClasspathEntry { Externalizer EXTERNALIZER = new Externalizer() { @Override - public AntClasspathEntry readValue(Element dataElement) throws InvalidDataException { + public AntClasspathEntry readValue(Element dataElement) { String pathUrl = dataElement.getAttributeValue(SinglePathEntry.PATH); - if (pathUrl != null) + if (pathUrl != null) { return new SinglePathEntry(PathUtil.toPresentableUrl(pathUrl)); + } String dirUrl = dataElement.getAttributeValue(AllJarsUnderDirEntry.DIR); - if (dirUrl != null) + if (dirUrl != null) { return new AllJarsUnderDirEntry(PathUtil.toPresentableUrl(dirUrl)); - throw new InvalidDataException(); + } + throw new IllegalStateException(); } @Override - public void writeValue(Element dataElement, AntClasspathEntry entry) throws WriteExternalException { + public void writeValue(Element dataElement, AntClasspathEntry entry) { entry.writeExternal(dataElement); } }; - void writeExternal(Element dataElement) throws WriteExternalException; + void writeExternal(Element dataElement); void addFilesTo(List files); @@ -60,7 +60,7 @@ public interface AntClasspathEntry { abstract class AddEntriesFactory implements NullableFactory> { private final JComponent myParentComponent; private final FileChooserDescriptor myDescriptor; - private final Function myMapper; + private final Function myMapper; public AddEntriesFactory(final JComponent parentComponent, final FileChooserDescriptor descriptor, diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java index 12c8d141b79e..2e9405564a3d 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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,8 +17,6 @@ package com.intellij.lang.ant.config.impl; import com.intellij.lang.ant.AntBundle; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.JarUtil; import com.intellij.util.config.*; import com.intellij.util.containers.Convertor; @@ -62,18 +60,18 @@ public class AntInstallation { } public static final Externalizer EXTERNALIZER = new Externalizer() { - public AntInstallation readValue(Element dataElement) throws InvalidDataException { + public AntInstallation readValue(Element dataElement) { AntInstallation antInstallation = new AntInstallation(); antInstallation.readExternal(dataElement); return antInstallation; } - public void writeValue(Element dataElement, AntInstallation antInstallation) throws WriteExternalException { + public void writeValue(Element dataElement, AntInstallation antInstallation) { antInstallation.myProperties.writeExternal(dataElement); } }; - private void readExternal(Element dataElement) throws InvalidDataException { + private void readExternal(Element dataElement) { myProperties.readExternal(dataElement); File antJar = new File(HOME_DIR.get(myProperties), PATH_TO_ANT_JAR); updateVersion(antJar); diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java index f9f8d0d9eb9f..c3133da1350f 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,6 @@ import com.intellij.execution.CantRunException; import com.intellij.lang.ant.AntBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.InvalidDataException; import com.intellij.util.config.AbstractProperty; import com.intellij.util.config.Externalizer; import org.jdom.Element; @@ -35,11 +34,13 @@ public abstract class AntReference { @NonNls private static final String BUNDLED_ANT_ATTR = "bundledAnt"; public static final Externalizer EXTERNALIZER = new Externalizer() { - public AntReference readValue(Element dataElement) throws InvalidDataException { + public AntReference readValue(Element dataElement) { if (Boolean.valueOf(dataElement.getAttributeValue(PROJECT_DEFAULT_ATTR)).booleanValue()) return PROJECT_DEFAULT; if (Boolean.valueOf(dataElement.getAttributeValue(BUNDLED_ANT_ATTR)).booleanValue()) return BUNDLED_ANT; String name = dataElement.getAttributeValue(NAME_ATTR); - if (name == null) throw new InvalidDataException(); + if (name == null) { + throw new IllegalStateException("no name"); + } return new MissingAntReference(name); } diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java index 43655b0463b4..d0166ffef749 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,8 +31,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.config.*; @@ -102,24 +100,13 @@ public class GlobalAntConfiguration implements PersistentStateComponent @Override public Element getState() { Element element = new Element("state"); - try { - myProperties.writeExternal(element); - } - catch (WriteExternalException e) { - LOG.error(e); - return null; - } + myProperties.writeExternal(element); return element; } @Override public void loadState(Element state) { - try { - myProperties.readExternal(state); - } - catch (InvalidDataException e) { - LOG.error(e); - } + myProperties.readExternal(state); } public static GlobalAntConfiguration getInstance() { diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java index 76581fd86f0c..ac982d676255 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,8 +18,6 @@ package com.intellij.lang.ant.config.impl; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.roots.ui.CellAppearanceEx; import com.intellij.openapi.roots.ui.FileAppearanceService; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -51,12 +49,12 @@ public class SinglePathEntry implements AntClasspathEntry { this(new File(osPath)); } - public void readExternal(final Element element) throws InvalidDataException { + public void readExternal(final Element element) { String value = element.getAttributeValue(PATH); myFile = new File(PathUtil.toPresentableUrl(value)); } - public void writeExternal(final Element element) throws WriteExternalException { + public void writeExternal(final Element element) { String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, myFile.getAbsolutePath().replace(File.separatorChar, '/')); element.setAttribute(PATH, url); } diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index 0756d656a55a..2a7103ceb9cf 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 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.coverage.view; import com.intellij.coverage.*; @@ -235,9 +250,13 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { : PsiFile.EMPTY_ARRAY; } }); - for (PsiFile file : childFiles) { + for (final PsiFile file : childFiles) { if (file instanceof PsiJavaFile) { - PsiClass[] classes = ((PsiJavaFile)file).getClasses(); + PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass[] compute() { + return ((PsiJavaFile) file).getClasses(); + } + }); if (classes.length > 0) { PsiClass aClass = classes[0]; if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; diff --git a/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java b/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java index 41ca3c2de064..758f83249519 100644 --- a/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java +++ b/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java @@ -52,9 +52,13 @@ public class GenerationHelper { } public static String getParamName(FieldElement fieldElement, Project project) { + JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); + return codeStyleManager.propertyNameToVariableName(getPropertyName(fieldElement, project), VariableKind.PARAMETER); + } + + public static String getPropertyName(FieldElement fieldElement, Project project) { String name = fieldElement.getName(); JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); - String propertyName = codeStyleManager.variableNameToPropertyName(name, VariableKind.FIELD); - return codeStyleManager.propertyNameToVariableName(propertyName, VariableKind.PARAMETER); + return codeStyleManager.variableNameToPropertyName(name, VariableKind.FIELD); } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java index ad1812886cc0..dd51519db9f5 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java @@ -217,15 +217,14 @@ public class GithubApiUtil { } @NotNull - public static String getReadOnlyToken(@NotNull GithubConnection connection, - @NotNull String user, - @NotNull String repo, - @NotNull String note) + public static String getTasksToken(@NotNull GithubConnection connection, + @NotNull String user, + @NotNull String repo, + @NotNull String note) throws IOException { GithubRepo repository = getDetailedRepoInfo(connection, user, repo); - // TODO: use read-only token for private repos when it will be available - List scopes = repository.isPrivate() ? Collections.singletonList("repo") : Collections.emptyList(); + List scopes = repository.isPrivate() ? Collections.singletonList("repo") : Collections.singletonList("public_repo"); return getScopedToken(connection, scopes, note); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java index a8445b7f76ac..d59ac54e3a0b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java @@ -55,7 +55,7 @@ public class GithubRepository extends BaseRepositoryImpl { public GithubRepository(GithubRepositoryType type) { super(type); - setUrl(GithubApiUtil.DEFAULT_GITHUB_HOST); + setUrl("https://" + GithubApiUtil.DEFAULT_GITHUB_HOST); } @NotNull diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java index ba863621c969..e3e8daabb56a 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java @@ -130,7 +130,7 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor + com.intellij.codeInspection.capitalization.AnnotateCapitalizationIntention diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java new file mode 100644 index 000000000000..1dc726b8a2ee --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java @@ -0,0 +1,237 @@ +/* + * Copyright 2000-2015 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.codeInspection; + +import com.intellij.codeInspection.ex.BaseLocalInspectionTool; +import com.intellij.lang.properties.*; +import com.intellij.lang.properties.ResourceBundle; +import com.intellij.lang.properties.customizeActions.DissociateResourceBundleAction; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.InputValidator; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; +import com.intellij.reference.SoftLazyValue; +import com.intellij.ui.AnActionButton; +import com.intellij.ui.AnActionButtonRunnable; +import com.intellij.ui.ToolbarDecorator; +import com.intellij.ui.components.JBList; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashSet; +import org.jdom.Element; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * @author Dmitry Batkovich + */ +public class SuspiciousLocalesLanguagesInspection extends BaseLocalInspectionTool { + private static final String ADDITIONAL_LANGUAGES_ATTR_NAME = "additionalLanguages"; + private final static SoftLazyValue> JAVA_LOCALES = new SoftLazyValue>() { + @NotNull + @Override + protected Set compute() { + final Set result = new HashSet(); + for (Locale locale : Locale.getAvailableLocales()) { + result.add(locale.getLanguage()); + } + return result; + } + }; + + private final List myAdditionalLanguages = new ArrayList(); + + @Nls + @NotNull + @Override + public String getDisplayName() { + return "Suspicious resource bundle locale languages"; + } + + @TestOnly + public void setAdditionalLanguages(List additionalLanguages) { + myAdditionalLanguages.clear(); + myAdditionalLanguages.addAll(additionalLanguages); + } + + @Override + public void readSettings(@NotNull Element node) throws InvalidDataException { + final String rawLanguages = node.getAttributeValue(ADDITIONAL_LANGUAGES_ATTR_NAME); + if (rawLanguages != null) { + myAdditionalLanguages.clear(); + myAdditionalLanguages.addAll(StringUtil.split(rawLanguages, ",")); + } + } + + @Override + public void writeSettings(@NotNull Element node) throws WriteExternalException { + if (!myAdditionalLanguages.isEmpty()) { + final ArrayList uniqueLanguages = ContainerUtil.newArrayList(ContainerUtil.newHashSet(myAdditionalLanguages)); + Collections.sort(uniqueLanguages); + final String locales = StringUtil.join(uniqueLanguages, ","); + node.setAttribute(ADDITIONAL_LANGUAGES_ATTR_NAME, locales); + } + } + + @Nullable + @Override + public JComponent createOptionsPanel() { + return new MyOptions().getComponent(); + } + + @Nullable + @Override + public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) { + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file); + if (propertiesFile == null) { + return null; + } + final ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); + final List files = resourceBundle.getPropertiesFiles(); + if (!(resourceBundle instanceof ResourceBundleImpl) || files.size() < 2) { + return null; + } + List bundleLocales = ContainerUtil.mapNotNull(files, new Function() { + @Override + public Locale fun(PropertiesFile propertiesFile) { + final Locale locale = propertiesFile.getLocale(); + return locale == ResourceBundleManager.DEFAULT_LOCALE ? null : locale; + } + }); + bundleLocales = ContainerUtil.filter(bundleLocales, new Condition() { + @Override + public boolean value(Locale locale) { + return !JAVA_LOCALES.getValue().contains(locale.getLanguage()) && !myAdditionalLanguages.contains(locale.getLanguage()); + } + }); + if (bundleLocales.isEmpty()) { + return null; + } + final ProblemDescriptor descriptor = manager.createProblemDescriptor(file, + PropertiesBundle.message( + "resource.bundle.contains.locales.with.suspicious.locale.languages.desciptor"), + new DissociateResourceBundleQuickFix(resourceBundle), + ProblemHighlightType.WEAK_WARNING, + true); + return new ProblemDescriptor[] {descriptor}; + } + + private static class DissociateResourceBundleQuickFix implements LocalQuickFix { + private final ResourceBundle myResourceBundle; + + private DissociateResourceBundleQuickFix(ResourceBundle bundle) { + myResourceBundle = bundle; + } + + @Nls + @NotNull + @Override + public String getName() { + return getFamilyName(); + } + + @NotNull + @Override + public String getFamilyName() { + return PropertiesBundle.message("dissociate.resource.bundle.quick.fix.name"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + DissociateResourceBundleAction.dissociate(Collections.singleton(myResourceBundle), project); + } + } + + private class MyOptions { + private JBList myAdditionalLocalesList; + + public MyOptions() { + myAdditionalLocalesList = new JBList(new MyListModel()); + myAdditionalLocalesList.setCellRenderer(new DefaultListCellRenderer()); + } + + public JPanel getComponent() { + final JPanel panel = new JPanel(new BorderLayout()); + panel.add(new JLabel(PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.label")), BorderLayout.NORTH); + panel.add( + ToolbarDecorator.createDecorator(myAdditionalLocalesList) + .setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + Messages.showInputDialog(panel, PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.input.text"), + PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.input.title"), null, "", new InputValidator() { + @Override + public boolean checkInput(String inputString) { + return 1 < inputString.length() && inputString.length() < 9 && !myAdditionalLanguages.contains(inputString); + } + + @Override + public boolean canClose(String inputString) { + if (inputString != null) { + myAdditionalLanguages.add(inputString); + ((MyListModel)myAdditionalLocalesList.getModel()).fireContentsChanged(); + } + return true; + } + }); + } + }) + .setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + final int index = myAdditionalLocalesList.getSelectedIndex(); + if (index > -1 && index < myAdditionalLanguages.size()) { + myAdditionalLanguages.remove(index); + ((MyListModel)myAdditionalLocalesList.getModel()).fireContentsChanged(); + } + } + }) + .setPreferredSize(new Dimension(-1, 100)) + .disableUpDownActions() + .createPanel(), + BorderLayout.CENTER); + return panel; + } + + private class MyListModel extends AbstractListModel { + @Override + public int getSize() { + return myAdditionalLanguages.size(); + } + + @Override + public Object getElementAt(int index) { + return myAdditionalLanguages.get(index); + } + + public void fireContentsChanged() { + fireContentsChanged(myAdditionalLanguages, -1, -1); + } + } + } +} diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p_en.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p_en.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties new file mode 100644 index 000000000000..cb17b36e6685 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties new file mode 100644 index 000000000000..cb17b36e6685 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p_asd.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p_asd.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java new file mode 100644 index 000000000000..891b8fcffe34 --- /dev/null +++ b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2015 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.codeInspection; + +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.containers.ContainerUtil; + +import java.io.File; + +/** + * @author Dmitry Batkovich + */ +public class SuspiciousLanguagesInspectionTest extends LightCodeInsightFixtureTestCase { + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("java-i18n") + "/testData/inspections/suspiciousLanguages"; + } + + public void testSimple1() { + doTest("p.properties", "p_en.properties"); + } + + public void testSimple2() { + doTest("p.properties", "p_asd.properties"); + } + + public void testWithAdditionalLocales() { + doTest("p.properties", "p_asd.properties", "asd"); + } + + private void doTest(final String file1, final String file2, final String... additionalLocales) { + myFixture.configureByFile(getTestName(true) + "/" + file1); + myFixture.configureByFile(getTestName(true) + "/" + file2); + final SuspiciousLocalesLanguagesInspection inspection = new SuspiciousLocalesLanguagesInspection(); + if (additionalLocales.length != 0) { + inspection.setAdditionalLanguages(ContainerUtil.newArrayList(additionalLocales)); + } + myFixture.enableInspections(inspection); + myFixture.checkHighlighting(); + } +} diff --git a/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft b/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft index 6d2a3b3c12af..72577b0ea7d8 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft +++ b/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft @@ -1,4 +1,5 @@ import junit.framework.TestCase; +#parse("File Header.java") public class ${NAME} extends TestCase { ${BODY} } \ No newline at end of file diff --git a/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft b/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft index 5d58064d098f..cc1f599bfbb6 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft +++ b/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft @@ -1,4 +1,5 @@ import static org.junit.Assert.*; +#parse("File Header.java") public class ${NAME} { ${BODY} } \ No newline at end of file diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java index 3fba1a3d9b7a..dae5c95b0241 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java @@ -41,6 +41,10 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner { final Runner testRunner = request.getRunner(); try { Description description = testRunner.getDescription(); + if (description == null) { + System.err.println("Nothing found to run. Runner " + testRunner.getClass().getName() + " provides no description."); + return -1; + } if (request instanceof ClassRequest) { description = getSuiteMethodDescription(request, description); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java index 26df2720e259..f3bcf765e5f5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,7 @@ import com.intellij.javaee.ExternalResourceManager; import com.intellij.javaee.ExternalResourceManagerEx; import com.intellij.javaee.ResourceRegistrar; import com.intellij.javaee.StandardResourceProvider; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -28,6 +28,7 @@ public class MavenSchemaProvider implements StandardResourceProvider { public static final String MAVEN_PROFILES_SCHEMA_URL = "http://maven.apache.org/xsd/profiles-1.0.0.xsd"; public static final String MAVEN_SETTINGS_SCHEMA_URL = "http://maven.apache.org/xsd/settings-1.0.0.xsd"; + @Override public void registerResources(ResourceRegistrar registrar) { registrar.addStdResource("http://maven.apache.org/maven-v4_0_0.xsd", "/schemas/maven-4.0.0.xsd", getClass()); registrar.addStdResource(MAVEN_PROJECT_SCHEMA_URL, "/schemas/maven-4.0.0.xsd", getClass()); @@ -41,7 +42,7 @@ public class MavenSchemaProvider implements StandardResourceProvider { String location = ((ExternalResourceManagerEx)ExternalResourceManager.getInstance()).getStdResource(url, null); assert location != null : "cannot find a standard resource for " + url; - VirtualFile result = VfsUtil.findRelativeFile(location, null); + VirtualFile result = VfsUtilCore.findRelativeFile(location, null); assert result != null : "cannot find a schema file for URL: " + url + " location: " + location; return result; diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties index aefabc574b38..1a58d5b832a4 100644 --- a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties +++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties @@ -60,3 +60,9 @@ inline.property.confirmation=Inline property ''{0}'' with value ''{1}''? alpha.unsorted.properties.file.inspection.display.name=Properties File or Resource Bundle is Alphabetically Unsorted trailing.spaces.in.property.inspection.ignore.visible.spaces=Ignore visible whitespaces + +resource.bundle.contains.locales.with.suspicious.locale.languages.desciptor=Resource bundle contains locales with suspicious locale languages +dissociate.resource.bundle.quick.fix.name=Dissociate Resource Bundle +dissociate.resource.bundle.quick.fix.options.label=Additional language codes\: +dissociate.resource.bundle.quick.fix.options.input.text=Inter language code +dissociate.resource.bundle.quick.fix.options.input.title=Additional Locale Languages diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index 5d8487d468a2..626961e8b9f2 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -47,7 +47,7 @@ import java.util.regex.Matcher; }) public class ResourceBundleManager implements PersistentStateComponent { private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class); - private final static Locale DEFAULT_LOCALE = new Locale("", "", ""); + public final static Locale DEFAULT_LOCALE = new Locale("", "", ""); private ResourceBundleManagerState myState = new ResourceBundleManagerState(); @@ -172,7 +172,11 @@ public class ResourceBundleManager implements PersistentStateComponent resourceBundles = extractResourceBundles(e); assert resourceBundles.size() > 0; - final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); - for (ResourceBundle resourceBundle : resourceBundles) { - fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); - for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { - fileEditorManager.closeFile(propertiesFile.getVirtualFile()); - } - ResourceBundleManager.getInstance(e.getProject()).dissociateResourceBundle(resourceBundle); - } - ProjectView.getInstance(project).refresh(); + dissociate(resourceBundles, project); } @Override @@ -79,6 +75,26 @@ public class DissociateResourceBundleAction extends AnAction { } } + public static void dissociate(final Collection resourceBundles, final Project project) { + final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + final Set toUpdateInProjectView = new HashSet(); + for (ResourceBundle resourceBundle : resourceBundles) { + fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); + for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { + fileEditorManager.closeFile(propertiesFile.getVirtualFile()); + PsiDirectory containingDirectory = propertiesFile.getContainingFile().getContainingDirectory(); + if (containingDirectory != null) { + toUpdateInProjectView.add(containingDirectory); + } + } + ResourceBundleManager.getInstance(project).dissociateResourceBundle(resourceBundle); + } + AbstractTreeBuilder treeBuilder = ProjectView.getInstance(project).getCurrentProjectViewPane().getTreeBuilder(); + for (PsiFileSystemItem item : toUpdateInProjectView) { + treeBuilder.queueUpdateFrom(item, false); + } + } + @NotNull private static Collection extractResourceBundles(final AnActionEvent event) { final Set targetResourceBundles = new HashSet(); diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java index b9f61643095d..20af8439004c 100644 --- a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java +++ b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java @@ -32,6 +32,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -97,4 +98,12 @@ public class ResourceBundleNode extends ProjectViewNode{ public Comparable getTypeSortKey() { return new PsiFileNode.ExtensionSortKey(StdFileTypes.PROPERTIES.getDefaultExtension()); } + + @Override + public boolean validate() { + if (!super.validate()) { + return false; + } + return Comparing.equal(getValue().getDefaultPropertiesFile().getResourceBundle(), getValue()); + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java index 99d2aca68ca5..3dd4744fc179 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java @@ -57,7 +57,7 @@ public class SvnPhantomChangeDiffRequestProvider implements ChangeDiffRequestPro @NotNull @Override public String getName() { - return "SVN Phantom Changes Viewer"; + return "SVN phantom changes viewer"; } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java index ed5245c639dc..35562e795f06 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java @@ -73,7 +73,7 @@ public class SvnTreeConflictDiffRequestProvider implements ChangeDiffRequestProv @NotNull @Override public String getName() { - return "SVN Phantom Changes Viewer"; + return "SVN tree conflict viewer"; } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java index 5f599aa4b55b..bf95f8694bd4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java @@ -9,7 +9,7 @@ public class SvnPropertiesDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Svn Properties Viewer"; + return "SVN properties viewer"; } @Override diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java new file mode 100644 index 000000000000..d875b3049281 --- /dev/null +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java @@ -0,0 +1,130 @@ +package com.intellij.tasks; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class CustomTaskState { + private String myId; + private String myPresentableName; + private boolean myPredefined; + + /** + * For serialization purposes only. + */ + public CustomTaskState() { + } + + public CustomTaskState(@NotNull String id, @NotNull String name) { + myId = id; + myPresentableName = name; + } + + /** + * Unique ID (e.g. number or unique name) of this state that can be used later to update state of an issue + * in {@link TaskRepository#setTaskState(Task, CustomTaskState)}. + * + * @see TaskRepository#setTaskState(Task, CustomTaskState) + */ + @NotNull + public String getId() { + return myId; + } + + /** + * For serialization purposes only. + */ + public void setId(String id) { + myId = id; + } + + /** + * Text that describes this state and will be shown to user in UI (unlike ID it's not necessarily unique). + */ + @NotNull + public String getPresentableName() { + return myPresentableName; + } + + /** + * For serialization purposes only. + */ + public void setPresentableName(@NotNull String name) { + myPresentableName = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CustomTaskState)) return false; + + final CustomTaskState state = (CustomTaskState)o; + + return myId.equals(state.myId); + } + + @Override + public int hashCode() { + return myId.hashCode(); + } + + /** + * Creates custom state for which ID is identical to {@link TaskState#name} of the given predefined state and {@link #isPredefined()} + * returns true. If your repository provides only fixed set of available states, that are one of those described in {@link TaskState}, + * you may find this methods useful to implement {@link TaskRepository#getAvailableTaskStates(Task)}. + * + * @return custom task state that represents given predefined state + * @see #asPredefined() + * @see #isPredefined() + * @see TaskRepository#getAvailableTaskStates(Task) + */ + @NotNull + public static CustomTaskState fromPredefined(@NotNull TaskState state) { + final CustomTaskState result = new CustomTaskState(state.name(), state.getPresentableName()); + result.setPredefined(true); + return result; + } + + /** + * Returns corresponding value of {@link TaskState} that has the same name as ID of this state. + * It's intended to be used for custom states created using {@link #fromPredefined}. + * + * @return predefined task state as described or {@code null} if such state doesn't exists or {@link #isPredefined()} returns false + * @see #isPredefined() + */ + @Nullable + public TaskState asPredefined() { + if (isPredefined()) { + try { + return TaskState.valueOf(getId()); + } + catch (IllegalArgumentException ignored) { + } + } + return null; + } + + /** + * Means that this custom state can be directly mapped to legacy {@link TaskState}. If it's false, {@link #asPredefined()} returns {@code null}. + * It's intended to be used mainly for compatibility with existing repositories. + * + * @see #asPredefined() + */ + private boolean isPredefined() { + return myPredefined; + } + + /** + * For serialization purposes only. + */ + public void setPredefined(boolean predefined) { + myPredefined = predefined; + } + + @Override + public String toString() { + return "CustomTaskState(id='" + myId + '\'' + ", name='" + myPresentableName + '\'' + ", predefined=" + myPredefined + ')'; + } +} diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java index 416a7158eb26..c6e270fdef4e 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java @@ -18,6 +18,10 @@ package com.intellij.tasks; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.impl.CancellableRunnable; +import com.intellij.tasks.impl.BaseRepository; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; import com.intellij.util.xmlb.annotations.Transient; @@ -26,6 +30,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.Set; import java.util.concurrent.Callable; /** @@ -34,7 +39,7 @@ import java.util.concurrent.Callable; * * @author Dmitry Avdeev * @see TaskRepositoryType - * @see com.intellij.tasks.impl.BaseRepository + * @see BaseRepository */ @Tag("server") public abstract class TaskRepository { @@ -109,7 +114,7 @@ public abstract class TaskRepository { /** * Returns an object that can test connection. - * {@link com.intellij.openapi.vcs.impl.CancellableRunnable#cancel()} should cancel the process. + * {@link CancellableRunnable#cancel()} should cancel the process. * * @return null if not supported */ @@ -164,6 +169,48 @@ public abstract class TaskRepository { return getIssues(query, offset, limit, withClosed); } + /** + * Retrieve states available for task from server. One of these states will be passed later to {@link #setTaskState(Task, TaskState)}. + * @param task task to update + * @return set of available states + */ + @NotNull + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + //noinspection unchecked + return ContainerUtil.map2Set(getRepositoryType().getPossibleTaskStates(), new Function() { + @Override + public CustomTaskState fun(TaskState state) { + return CustomTaskState.fromPredefined(state); + } + }); + } + + /** + * Remember state used when opening task most recently. + * @param state preferred task state + */ + public abstract void setPreferredOpenTaskState(@Nullable CustomTaskState state); + + /** + * Task state that was used last time when opening task. + * @return preferred task state + */ + @Nullable + public abstract CustomTaskState getPreferredOpenTaskState(); + + /** + * Remember state used when closing task most recently. + * @param state preferred task state + */ + public abstract void setPreferredCloseTaskState(@Nullable CustomTaskState state); + + /** + * Task state that was used last time when closing task. + * @return preferred task state + */ + @Nullable + public abstract CustomTaskState getPreferredCloseTaskState(); + /** * @param id task ID. Don't forget to define {@link #extractId(String)}, if your server uses not PROJECT-123 format for task IDs. * @return found task or {@code null} otherwise. Basically you should return {@code null} on e.g. 404 error and throw exception with @@ -179,19 +226,39 @@ public abstract class TaskRepository { @Nullable public abstract String extractId(@NotNull String taskName); + /** - * Update state of the task on server. Don't forget to add {@link #STATE_UPDATING} in {@link #getFeatures()} and - * supported states in {@link TaskRepositoryType#getPossibleTaskStates()}. - * - * @param task issue to update - * @param state new state of the issue - * @see com.intellij.tasks.TaskRepositoryType#getPossibleTaskStates() - * @see com.intellij.tasks.TaskRepository#getFeatures() + * @deprecated Use {@link #setTaskState(Task, CustomTaskState)} instead. */ + @Deprecated public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { throw new UnsupportedOperationException("Setting task to state " + state + " is not supported"); } + /** + * Update state of the task on server. It's guaranteed that only issues returned by {@link #getAvailableTaskStates(Task)} + * will be passed here. + *

    + * Don't forget to add {@link #STATE_UPDATING} in {@link #getFeatures()} and supported states in {@link #getAvailableTaskStates(Task)}. + * + * @param task issue to update + * @param state new state of the issue + * @see TaskRepositoryType#getPossibleTaskStates() + * @see TaskRepository#getFeatures() + */ + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { + TaskState predefinedState = null; + try { + predefinedState = TaskState.valueOf(state.getId()); + } + catch (IllegalArgumentException ignored) { + } + if (predefinedState != null) { + setTaskState(task, predefinedState); + } + } + + // for serialization public TaskRepository() { myType = null; diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java index f348f4264c22..d4575cf3eb92 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java @@ -67,8 +67,10 @@ public abstract class TaskRepositoryType implements Ta public abstract Class getRepositoryClass(); /** - * @return states that can be set by {@link TaskRepository#setTaskState(Task, TaskState)} + * @return states that can be set by {@link TaskRepository#setTaskState(Task, CustomTaskState)} + * @deprecated Use {@link TaskRepository#getAvailableTaskStates(Task)} instead. */ + @Deprecated public EnumSet getPossibleTaskStates() { return EnumSet.noneOf(TaskState.class); } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java index c0c0a2628b9d..79c504a44a60 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java @@ -15,16 +15,30 @@ */ package com.intellij.tasks; +import org.jetbrains.annotations.NotNull; + /** + * Predefined common task states were used before {@link CustomTaskState} was introduced. + * * @author Dmitry Avdeev */ public enum TaskState { + SUBMITTED("Submitted"), + OPEN("Open"), + IN_PROGRESS("In Progress"), + REOPENED("Reopened"), + RESOLVED("Resolved"), - SUBMITTED, - OPEN, - IN_PROGRESS, - REOPENED, - RESOLVED, + OTHER("Other"); - OTHER + private String myPresentableName; + + TaskState(@NotNull String presentableName) { + myPresentableName = presentableName; + } + + @NotNull + public String getPresentableName() { + return myPresentableName; + } } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java index 8423736c8c10..0f67d4bae909 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java @@ -18,6 +18,7 @@ package com.intellij.tasks.impl; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.PasswordUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.TaskRepository; import com.intellij.tasks.TaskRepositoryType; import com.intellij.util.xmlb.annotations.Tag; @@ -40,6 +41,8 @@ public abstract class BaseRepository extends TaskRepository { protected boolean myUseProxy; protected boolean myUseHttpAuthentication; protected boolean myLoginAnonymously; + protected CustomTaskState myPreferredOpenTaskState; + private CustomTaskState myPreferredCloseTaskState; public BaseRepository(TaskRepositoryType type) { super(type); @@ -135,6 +138,28 @@ public abstract class BaseRepository extends TaskRepository { myLoginAnonymously = loginAnonymously; } + @Override + public void setPreferredOpenTaskState(@Nullable CustomTaskState state) { + myPreferredOpenTaskState = state; + } + + @Nullable + @Override + public CustomTaskState getPreferredOpenTaskState() { + return myPreferredOpenTaskState; + } + + @Override + public void setPreferredCloseTaskState(@Nullable CustomTaskState state) { + myPreferredCloseTaskState = state; + } + + @Nullable + @Override + public CustomTaskState getPreferredCloseTaskState() { + return myPreferredCloseTaskState; + } + @Nullable public String extractId(@NotNull String taskName) { Matcher matcher = PATTERN.matcher(taskName); diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java index 8ee9c97512a1..7b760769a0e3 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java @@ -1,8 +1,8 @@ package com.intellij.tasks.jira; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; -import com.intellij.tasks.TaskState; import com.intellij.tasks.jira.rest.api2.JiraRestApi2; import com.intellij.tasks.jira.rest.api20alpha1.JiraRestApi20Alpha1; import com.intellij.tasks.jira.soap.JiraLegacyApi; @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Set; /** * Because of the number of available remote interfaces in JIRA, {@link JiraRepository} delegates @@ -29,7 +30,10 @@ public abstract class JiraRemoteApi { @Nullable public abstract Task findTask(@NotNull String key) throws Exception; - public abstract void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception; + @NotNull + public abstract Set getAvailableTaskStates(@NotNull Task task) throws Exception; + + public abstract void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception; public abstract void updateTimeSpend(@NotNull LocalTask task, @NotNull String timeSpent, String comment) throws Exception; @@ -80,6 +84,5 @@ public abstract class JiraRemoteApi { public String getVersionName() { return myVersionName; } - } } diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java index 820bb22426e0..ec0e612f4e81 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java @@ -22,10 +22,10 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; -import com.intellij.tasks.TaskState; import com.intellij.tasks.impl.BaseRepositoryImpl; import com.intellij.tasks.impl.gson.GsonUtil; import com.intellij.tasks.jira.rest.JiraRestApi; @@ -44,10 +44,7 @@ import org.jetbrains.annotations.Nullable; import java.io.InputStream; import java.net.URL; -import java.util.Collections; -import java.util.Hashtable; -import java.util.List; -import java.util.Vector; +import java.util.*; import java.util.regex.Pattern; /** @@ -352,10 +349,16 @@ public class JiraRepository extends BaseRepositoryImpl { } @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { myApiVersion.setTaskState(task, state); } + @NotNull + @Override + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + return myApiVersion.getAvailableTaskStates(task); + } + public void setSearchQuery(String searchQuery) { mySearchQuery = searchQuery; } @@ -371,8 +374,6 @@ public class JiraRepository extends BaseRepositoryImpl { /** * Used to preserve discovered API version for the next initialization. - * - * @return */ @SuppressWarnings("UnusedDeclaration") @Nullable diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java index 502eed083e74..78919e390d5f 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java @@ -2,8 +2,8 @@ package com.intellij.tasks.jira.rest; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.Task; -import com.intellij.tasks.TaskState; import com.intellij.tasks.jira.JiraRemoteApi; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.JiraVersion; @@ -99,19 +99,16 @@ public abstract class JiraRestApi extends JiraRemoteApi { protected abstract JiraIssue parseIssue(String response); @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { String requestBody = getRequestForStateTransition(state); LOG.debug(String.format("Transition: %s -> %s, request: %s", task.getState(), state, requestBody)); - if (requestBody == null) { - return; - } PostMethod method = new PostMethod(myRepository.getRestUrl("issue", task.getId(), "transitions")); method.setRequestEntity(createJsonEntity(requestBody)); myRepository.executeMethod(method); } @Nullable - protected abstract String getRequestForStateTransition(@NotNull TaskState state); + protected abstract String getRequestForStateTransition(@NotNull CustomTaskState state); protected static RequestEntity createJsonEntity(String requestBody) { try { diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java index 0c9b647ee720..b83607481fac 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java @@ -3,11 +3,13 @@ package com.intellij.tasks.jira.rest.api2; import com.google.gson.reflect.TypeToken; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; -import com.intellij.tasks.TaskState; +import com.intellij.tasks.Task; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.rest.JiraRestApi; import com.intellij.tasks.jira.rest.api2.model.JiraIssueApi2; +import com.intellij.tasks.jira.rest.api2.model.JiraTransitionsWrapperApi2; import com.intellij.tasks.jira.rest.model.JiraIssue; import com.intellij.tasks.jira.rest.model.JiraResponseWrapper; import org.apache.commons.httpclient.methods.GetMethod; @@ -18,6 +20,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * This REST API version is used in JIRA 5.1.8 and above (including JIRA 6.x.x). @@ -63,21 +66,31 @@ public class JiraRestApi2 extends JiraRestApi { return JiraRepository.GSON.fromJson(response, JiraIssueApi2.class); } - @Nullable + @NotNull @Override - protected String getRequestForStateTransition(@NotNull TaskState state) { - // REST API 2.0 require double quotes both around field names and values (even numbers) - switch (state) { - case IN_PROGRESS: - return "{\"transition\": {\"id\": \"4\"}}"; - case RESOLVED: - // 5 for "Resolved", 2 for "Closed" - return "{\"transition\": {\"id\": \"5\"}, \"fields\": {\"resolution\": {\"name\": \"Fixed\"}}}"; - case REOPENED: - return "{\"transition\": {\"id\": \"3\"}}"; - default: - return null; + protected String getRequestForStateTransition(@NotNull CustomTaskState state) { + assert StringUtil.isNotEmpty(state.getId()); + final String stateId = state.getId(); + final int index = stateId.indexOf(':'); + if (index >= 0) { + return "{" + + " \"transition\": {\"id\": \"" + stateId.substring(0, index) + "\"}, " + + " \"fields\": {\"resolution\": {\"name\": \"" + stateId.substring(index + 1) + "\"}}" + + "}"; } + else { + return "{\"transition\": {\"id\": \"" + stateId + "\"}}"; + } + } + + @NotNull + @Override + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + final GetMethod method = new GetMethod(myRepository.getRestUrl("issue", task.getId(), "transitions")); + method.setQueryString("expand=transitions.fields"); + final String response = myRepository.executeMethod(method); + final JiraTransitionsWrapperApi2 wrapper = JiraRepository.GSON.fromJson(response, JiraTransitionsWrapperApi2.class); + return wrapper.getTransitions(); } @Override diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java new file mode 100644 index 000000000000..a1534ab81e8a --- /dev/null +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java @@ -0,0 +1,68 @@ +package com.intellij.tasks.jira.rest.api2.model; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.tasks.CustomTaskState; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +/** + * @author Mikhail Golubev + */ +@SuppressWarnings({"unused", "FieldMayBeFinal"}) +public class JiraTransitionsWrapperApi2 { + private static final Logger LOG = Logger.getInstance(JiraTransitionsWrapperApi2.class); + private List transitions = Collections.emptyList(); + + static class JiraTransition { + private int id; + private String name; + @SerializedName("to") + private JiraTaskState target; + private JsonObject fields; + + static class JiraTaskState { + private int id; + private String name; + } + } + + @NotNull + public Set getTransitions() { + final Set result = new LinkedHashSet(); + nextTransition: + for (JiraTransition transition : transitions) { + final String stateName = transition.target.name; + final List resolutions = new ArrayList(); + if (transition.fields != null) { + for (Map.Entry field : transition.fields.entrySet()) { + final String fieldName = field.getKey(); + final JsonObject fieldInfo = field.getValue().getAsJsonObject(); + if (fieldInfo.get("required").getAsBoolean()) { + if (fieldName.equals("resolution")) { + for (JsonElement allowedValue : fieldInfo.getAsJsonArray("allowedValues")) { + resolutions.add(allowedValue.getAsJsonObject().get("name").getAsString()); + } + } + else { + LOG.info("Unknown required field '" + fieldName + "' for transition '" + stateName + "'"); + continue nextTransition; + } + } + } + } + if (resolutions.isEmpty()) { + result.add(new CustomTaskState(String.valueOf(transition.id), stateName)); + } + else { + for (String resolution : resolutions) { + result.add(new CustomTaskState(transition.id + ":" + resolution, stateName + " (" + resolution + ")")); + } + } + } + return result; + } +} diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java index 7de17945ac31..bc70d239ce73 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java @@ -2,9 +2,10 @@ package com.intellij.tasks.jira.rest.api20alpha1; import com.google.gson.reflect.TypeToken; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; +import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; -import com.intellij.tasks.TaskState; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.rest.JiraRestApi; import com.intellij.tasks.jira.rest.JiraRestTask; @@ -16,20 +17,35 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * This REST API is used in JIRA versions from 4.2 to 4.4. + * * @author Mikhail Golubev */ public class JiraRestApi20Alpha1 extends JiraRestApi { private static final Logger LOG = Logger.getInstance(JiraRestApi20Alpha1.class); - private static final Type ISSUES_WRAPPER_TYPE = new TypeToken>() { /* empty */ }.getType(); + private static final Type ISSUES_WRAPPER_TYPE = new TypeToken>() {/* empty */}.getType(); public JiraRestApi20Alpha1(JiraRepository repository) { super(repository); } + @NotNull + @Override + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + // REST API of JIRA 4.x for retrieving possible transitions is very limited: we can't fetch possible resolutions and + // names of transition destinations. So we have no other options than to hardcode them. + final HashSet result = new HashSet(); + result.add(new CustomTaskState("4", "In Progress")); + result.add(new CustomTaskState("5", "Resolved (Fixed)")); + result.add(new CustomTaskState("3", "Reopened")); + return result; + } + @Override protected JiraIssue parseIssue(String response) { return JiraRepository.GSON.fromJson(response, JiraIssueApi20Alpha1.class); @@ -57,20 +73,24 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { @Nullable @Override - protected String getRequestForStateTransition(@NotNull TaskState state) { - switch (state) { - case IN_PROGRESS: - return "{\"transition\": \"4\"}"; - case RESOLVED: - // 5 for "Resolved", 2 for "Closed" - return "{\"transition\": \"5\", \"resolution\": \"Fixed\"}"; - case REOPENED: - return "{\"transition\": \"3\"}"; - default: - return null; + protected String getRequestForStateTransition(@NotNull CustomTaskState state) { + try { + switch (Integer.parseInt(state.getId())) { + case 4: // In Progress + return "{\"transition\": \"4\"}"; + case 5: // Resolved (2 for "Closed") + return "{\"transition\": \"5\", \"resolution\": \"Fixed\"}"; + case 3: // Reopened + return "{\"transition\": \"3\"}"; + } } + catch (NumberFormatException ignored) { + } + LOG.error("Unknown ID of predefined issue state: " + state.getId()); + return null; } + @Override public void updateTimeSpend(@NotNull LocalTask task, @NotNull String timeSpent, String comment) throws Exception { throw new Exception(TaskBundle.message("jira.failure.no.time.spent")); diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java index e8cbee842cda..7f5ab27cc9a1 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java @@ -1,10 +1,10 @@ package com.intellij.tasks.jira.soap; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; -import com.intellij.tasks.TaskState; import com.intellij.tasks.impl.TaskUtil; import com.intellij.tasks.jira.JiraRemoteApi; import com.intellij.tasks.jira.JiraRepository; @@ -19,7 +19,9 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.List; +import java.util.Set; /** * Legacy integration restored due to IDEA-120595. @@ -102,8 +104,14 @@ public class JiraLegacyApi extends JiraRemoteApi { return ApiType.LEGACY; } + @NotNull @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + return Collections.emptySet(); + } + + @Override + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { throw new Exception(TaskBundle.message("jira.failure.no.state.update")); } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties b/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties index ce617cbf01ca..4d631b7c5d20 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties @@ -23,3 +23,5 @@ youtrack.default.query=for: me sort by: updated #Unresolved bugzilla.failure.malformed.response=Cannot decode server response. Check that XML-RPC plugin is enabled. bugzilla.failure.no.version=Cannot find Bugzilla version. Check that URL ends with "xmlrpc.cgi". +## Trello +trello.failure.write.access.required=This action requires write access to your account. Please update authorization token in settings. diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java index 6863eef78510..7bf2afa94b2f 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java @@ -41,11 +41,13 @@ public class CloseTaskAction extends BaseTaskAction { LocalTask task = taskManager.getActiveTask(); CloseTaskDialog dialog = new CloseTaskDialog(project, task); if (dialog.showAndGet()) { - if (dialog.isCloseIssue()) { + final CustomTaskState taskState = dialog.getCloseIssueState(); + if (taskState != null) { try { TaskRepository repository = task.getRepository(); assert repository != null; - repository.setTaskState(task, TaskState.RESOLVED); + repository.setTaskState(task, taskState); + repository.setPreferredCloseTaskState(taskState); } catch (Exception e1) { Messages.showErrorDialog(project, e1.getMessage(), "Cannot Resolve Issue"); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form index 0c8600a9785b..7508f5a7dc34 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form @@ -3,7 +3,7 @@ - + @@ -52,14 +52,6 @@ - - - - - - - - @@ -73,6 +65,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java index fa9879c05fe0..73d14d23435a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java @@ -19,42 +19,51 @@ package com.intellij.tasks.actions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.vcs.VcsType; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.TaskManager; import com.intellij.tasks.TaskRepository; -import com.intellij.tasks.TaskState; import com.intellij.tasks.impl.TaskManagerImpl; +import com.intellij.tasks.impl.TaskStateCombo; import com.intellij.tasks.impl.TaskUtil; import com.intellij.ui.components.JBCheckBox; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.Collection; /** * @author Dmitry Avdeev */ public class CloseTaskDialog extends DialogWrapper { - + private final Project myProject; + private final LocalTask myTask; private JCheckBox myCommitChanges; - private JCheckBox myCloseIssue; private JPanel myPanel; private JLabel myTaskLabel; private JBCheckBox myMergeBranches; private JPanel myVcsPanel; + private JLabel myStateComboBoxLabel; + private TaskStateCombo myStateCombo; private final TaskManagerImpl myTaskManager; - public CloseTaskDialog(Project project, LocalTask task) { + public CloseTaskDialog(Project project, final LocalTask task) { super(project, false); + myProject = project; + myTask = task; setTitle("Close Task"); myTaskLabel.setText(TaskUtil.getTrimmedSummary(task)); myTaskLabel.setIcon(task.getIcon()); - TaskRepository repository = task.getRepository(); - boolean visible = task.isIssue() && TaskUtil.isStateSupported(repository, TaskState.RESOLVED); - myCloseIssue.setVisible(visible); + myStateComboBoxLabel.setLabelFor(myStateCombo); + if (!TaskStateCombo.isStateSupportedFor(task)) { + myStateComboBoxLabel.setVisible(false); + myStateCombo.setVisible(false); + } myTaskManager = (TaskManagerImpl)TaskManager.getManager(project); - myCloseIssue.setSelected(visible && myTaskManager.getState().closeIssue); if (myTaskManager.isVcsEnabled()) { myCommitChanges.setEnabled(!task.getChangeLists().isEmpty()); @@ -71,6 +80,11 @@ public class CloseTaskDialog extends DialogWrapper { else { myVcsPanel.setVisible(false); } + final JComponent preferredFocusedComponent = getPreferredFocusedComponent(); + if (preferredFocusedComponent != null) { + myStateCombo.registerUpDownAction(preferredFocusedComponent); + } + myStateCombo.scheduleUpdate(); init(); } @@ -78,8 +92,15 @@ public class CloseTaskDialog extends DialogWrapper { return myPanel; } - boolean isCloseIssue() { - return myCloseIssue.isSelected(); + @Nullable + @Override + public JComponent getPreferredFocusedComponent() { + return myStateCombo.getComboBox(); + } + + @Nullable + CustomTaskState getCloseIssueState() { + return myStateCombo.getSelectedState(); } boolean isCommitChanges() { @@ -92,7 +113,6 @@ public class CloseTaskDialog extends DialogWrapper { @Override protected void doOKAction() { - myTaskManager.getState().closeIssue = isCloseIssue(); if (myCommitChanges.isEnabled()) { myTaskManager.getState().commitChanges = isCommitChanges(); } @@ -101,4 +121,14 @@ public class CloseTaskDialog extends DialogWrapper { } super.doOKAction(); } + + private void createUIComponents() { + myStateCombo = new TaskStateCombo(myProject, myTask) { + @Nullable + @Override + protected CustomTaskState getPreferredState(@NotNull TaskRepository repository, @NotNull Collection available) { + return repository.getPreferredCloseTaskState(); + } + }; + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form index fb7ab62bdaa8..64b57bd9d93b 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form @@ -1,9 +1,9 @@

    - + - + @@ -11,7 +11,7 @@ - + @@ -31,21 +31,12 @@ - - - - - - - - - - + @@ -76,7 +67,7 @@ - + @@ -124,7 +115,9 @@ - + + + @@ -137,6 +130,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 66c3f80540c5..485161687d68 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -30,6 +30,7 @@ import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.VcsTaskHandler; import com.intellij.tasks.*; import com.intellij.tasks.impl.TaskManagerImpl; +import com.intellij.tasks.impl.TaskStateCombo; import com.intellij.tasks.impl.TaskUtil; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.components.JBCheckBox; @@ -42,6 +43,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Collection; /** * @author Dmitry Avdeev @@ -53,7 +55,6 @@ public class OpenTaskDialog extends DialogWrapper { private JPanel myPanel; @BindControl(value = "clearContext", instant = true) private JCheckBox myClearContext; - private JCheckBox myMarkAsInProgressBox; private JLabel myTaskNameLabel; private JPanel myVcsPanel; private JTextField myBranchName; @@ -62,6 +63,8 @@ public class OpenTaskDialog extends DialogWrapper { private JBCheckBox myCreateChangelist; private JBLabel myFromLabel; private ComboBox myBranchFrom; + private JLabel myTaskStateLabel; + private TaskStateCombo myTaskStateCombo; private final Project myProject; private final Task myTask; @@ -81,10 +84,10 @@ public class OpenTaskDialog extends DialogWrapper { binder.bindAnnotations(this); binder.reset(); - TaskRepository repository = task.getRepository(); - myMarkAsInProgressBox.setSelected(manager.getState().markAsInProgress); - if (!TaskUtil.isStateSupported(repository, TaskState.IN_PROGRESS)) { - myMarkAsInProgressBox.setVisible(false); + myTaskStateLabel.setLabelFor(myTaskStateCombo); + if (!TaskStateCombo.isStateSupportedFor(task)) { + myTaskStateLabel.setVisible(false); + myTaskStateCombo.setVisible(false); } TaskManagerImpl.Config state = taskManager.getState(); @@ -162,6 +165,11 @@ public class OpenTaskDialog extends DialogWrapper { myChangelistName.setText(taskManager.getChangelistName(task)); updateFields(true); } + final JComponent preferredFocusedComponent = getPreferredFocusedComponent(); + if (preferredFocusedComponent != null) { + myTaskStateCombo.registerUpDownAction(preferredFocusedComponent); + } + myTaskStateCombo.scheduleUpdate(); init(); } @@ -186,14 +194,15 @@ public class OpenTaskDialog extends DialogWrapper { public void createTask() { final TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject); - taskManager.getState().markAsInProgress = isMarkAsInProgress(); taskManager.getState().createChangelist = myCreateChangelist.isSelected(); taskManager.getState().createBranch = myCreateBranch.isSelected(); - TaskRepository repository = myTask.getRepository(); - if (isMarkAsInProgress() && repository != null) { + final CustomTaskState taskState = myTaskStateCombo.getSelectedState(); + final TaskRepository repository = myTask.getRepository(); + if (repository != null && taskState != null) { try { - repository.setTaskState(myTask, TaskState.IN_PROGRESS); + repository.setTaskState(myTask, taskState); + repository.setPreferredOpenTaskState(taskState); } catch (Exception ex) { Messages.showErrorDialog(myProject, ex.getMessage(), "Cannot Set State For Issue"); @@ -252,10 +261,6 @@ public class OpenTaskDialog extends DialogWrapper { return myClearContext.isSelected(); } - private boolean isMarkAsInProgress() { - return myMarkAsInProgressBox.isSelected() && myMarkAsInProgressBox.isVisible(); - } - @NonNls protected String getDimensionServiceKey() { return "SimpleOpenTaskDialog"; @@ -270,11 +275,21 @@ public class OpenTaskDialog extends DialogWrapper { return myChangelistName; } else { - return null; + return myTaskStateCombo.getComboBox(); } } protected JComponent createCenterPanel() { return myPanel; } + + private void createUIComponents() { + myTaskStateCombo = new TaskStateCombo(myProject, myTask) { + @Nullable + @Override + protected CustomTaskState getPreferredState(@NotNull TaskRepository repository, @NotNull Collection available) { + return repository.getPreferredOpenTaskState(); + } + }; + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java index ec4d81f86d2c..5dabf0b91e3b 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -56,7 +56,7 @@ public class XDebuggerBreakpointsContextProvider extends WorkingContextProvider XBreakpointManagerImpl.BreakpointManagerState state = myBreakpointManager.getState(); Element serialize = XmlSerializer.serialize(state, new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accessor.read(bean) != null; } }); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java index 2b39f86d30b8..12fddd63d7f8 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -54,7 +54,7 @@ public class XDebuggerWatchesProvider extends WorkingContextProvider { XDebuggerWatchesManager.WatchesManagerState state = myWatchesManager.getState(); Element serialize = XmlSerializer.serialize(state, new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accessor.read(bean) != null; } }); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 3529dc1229e9..3a50bb8da92c 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -1034,13 +1034,11 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe public boolean createBranch = true; // close task options - public boolean closeIssue = true; public boolean commitChanges = true; public boolean mergeBranch = true; public boolean saveContextOnCommit = true; public boolean trackContextForNewChangelist = false; - public boolean markAsInProgress = false; public String changelistNameFormat = "{id} {summary}"; public String branchNameFormat = "{id}"; diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java new file mode 100644 index 000000000000..2126eece9902 --- /dev/null +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java @@ -0,0 +1,170 @@ +package com.intellij.tasks.impl; + +import com.intellij.ide.actions.TemplateKindCombo; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Trinity; +import com.intellij.tasks.CustomTaskState; +import com.intellij.tasks.Task; +import com.intellij.tasks.TaskRepository; +import com.intellij.tasks.impl.TaskUiUtil.ComboBoxUpdater; +import com.intellij.ui.ListCellRendererWrapper; +import com.intellij.ui.components.JBLabel; +import com.intellij.util.Function; +import com.intellij.util.PlatformIcons; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.util.Collection; +import java.util.List; + +/** + * @author Mikhail Golubev + */ +public abstract class TaskStateCombo extends JPanel { + private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --"); + + public static boolean isStateSupportedFor(@Nullable Task task) { + if (task == null || !task.isIssue()) { + return false; + } + final TaskRepository repository = task.getRepository(); + return repository != null && repository.isSupported(TaskRepository.STATE_UPDATING); + } + + private final Project myProject; + private final Task myTask; + private final TemplateKindCombo myKindCombo = new TemplateKindCombo(); + + // For designer only + @SuppressWarnings("unused") + public TaskStateCombo() { + this(null, null); + } + + @SuppressWarnings({"GtkPreferredJComboBoxRenderer", "unchecked"}) + public TaskStateCombo(Project project, Task task) { + myProject = project; + myTask = task; + + final JBLabel hintButton = new JBLabel(); + hintButton.setIcon(PlatformIcons.UP_DOWN_ARROWS); + hintButton.setToolTipText("Pressing Up or Down arrows while in editor changes the state"); + final JComboBox comboBox = myKindCombo.getComboBox(); + comboBox.setPreferredSize(new Dimension(300, UIUtil.fixComboBoxHeight(comboBox.getPreferredSize().height))); + final ListCellRenderer defaultRenderer = comboBox.getRenderer(); + comboBox.setRenderer(new ListCellRenderer() { + @SuppressWarnings({"unchecked", "GtkPreferredJComboBoxRenderer"}) + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value == null) { + return new ListCellRendererWrapper() { + @Override + public void customize(JList list, CustomStateTrinityAdapter value, int index, boolean selected, boolean hasFocus) { + setText("-- no states available --"); + } + }.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); + } + return defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + }); + + setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); + add(myKindCombo); + add(hintButton); + } + + public boolean scheduleUpdate() { + if (myProject != null && isStateSupportedFor(myTask)) { + final JComboBox comboBox = myKindCombo.getComboBox(); + final TaskRepository repository = myTask.getRepository(); + assert repository != null; + new ComboBoxUpdater(myProject, "Fetching available task states...", comboBox) { + @NotNull + @Override + protected List fetch(@NotNull ProgressIndicator indicator) throws Exception { + return CustomStateTrinityAdapter.wrapList(repository.getAvailableTaskStates(myTask)); + } + + @Nullable + @Override + public CustomStateTrinityAdapter getSelectedItem() { + final CustomTaskState state = getPreferredState(repository, CustomStateTrinityAdapter.unwrapList(myResult)); + return state != null ? new CustomStateTrinityAdapter(state) : null; + } + + @Nullable + @Override + public CustomStateTrinityAdapter getExtraItem() { + return new CustomStateTrinityAdapter(DO_NOT_UPDATE_STATE); + } + }.queue(); + return true; + } + return false; + } + + /** + * @return {@code null} if no state is available at the moment or special "do not update" state was selected + */ + @Nullable + public CustomTaskState getSelectedState() { + final CustomStateTrinityAdapter item = (CustomStateTrinityAdapter)myKindCombo.getComboBox().getSelectedItem(); + if (item == null) { + return null; + } + final CustomTaskState state = item.myState; + return state == DO_NOT_UPDATE_STATE ? null : state; + } + + public void registerUpDownAction(@NotNull JComponent focusable) { + myKindCombo.registerUpDownHint(focusable); + } + + @NotNull + public JComboBox getComboBox() { + return myKindCombo.getComboBox(); + } + + /** + * Determine what state should be initially selected in the list. + * @param repository task repository to communicate with + * @param available tasks states already downloaded from the repository + * @return task state to select + */ + @Nullable + protected abstract CustomTaskState getPreferredState(@NotNull TaskRepository repository, @NotNull Collection available); + + private static class CustomStateTrinityAdapter extends Trinity { + final CustomTaskState myState; + + public CustomStateTrinityAdapter(@NotNull CustomTaskState state) { + super(state.getPresentableName(), null, state.getId()); + myState = state; + } + + @NotNull + static List wrapList(@NotNull Collection states) { + return ContainerUtil.map(states, new Function() { + @Override + public CustomStateTrinityAdapter fun(CustomTaskState state) { + return new CustomStateTrinityAdapter(state); + } + }); + } + + @NotNull + static List unwrapList(@NotNull Collection wrapped) { + return ContainerUtil.map(wrapped, new Function() { + @Override + public CustomTaskState fun(CustomStateTrinityAdapter adapter) { + return adapter.myState; + } + }); + } + } +} diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java index d24ed38c9819..0f8e571a9e87 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java @@ -6,14 +6,14 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.ComboBox; +import com.intellij.tasks.config.TaskRepositoryEditor; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.List; +import java.util.Collection; /** * @author Mikhail Golubev @@ -33,13 +33,18 @@ public class TaskUiUtil { public abstract static class RemoteFetchTask extends Task.Backgroundable { protected T myResult; protected Exception myException; - private final ModalityState myModalityState = ModalityState.current(); + private final ModalityState myModalityState; /** * Should be called only from EDT, so current modality state can be captured. */ protected RemoteFetchTask(@Nullable Project project, @NotNull String title) { + this(project, title, ModalityState.current()); + } + + protected RemoteFetchTask(@Nullable Project project, @NotNull String title, @NotNull ModalityState modalityState) { super(project, title); + myModalityState = modalityState; } @Override @@ -55,7 +60,7 @@ public class TaskUiUtil { /** * {@link #onSuccess()} can't be used for this purpose, because it doesn't consider current modality state - * which will prevent UI updating in modal dialog (e.g. in {@link com.intellij.tasks.config.TaskRepositoryEditor}). + * which will prevent UI updating in modal dialog (e.g. in {@link TaskRepositoryEditor}). */ @Nullable @Override @@ -79,11 +84,11 @@ public class TaskUiUtil { * Auxiliary remote fetcher designed to simplify updating of combo boxes in repository editors, which is * indeed a rather common task. */ - public static abstract class ComboBoxUpdater extends RemoteFetchTask> { - protected final ComboBox myComboBox; + public static abstract class ComboBoxUpdater extends RemoteFetchTask> { + protected final JComboBox myComboBox; - public ComboBoxUpdater(@Nullable Project project, @NotNull String title, @NotNull ComboBox comboBox) { - super(project, title); + public ComboBoxUpdater(@Nullable Project project, @NotNull String title, @NotNull JComboBox comboBox) { + super(project, title, ModalityState.any()); myComboBox = comboBox; } @@ -99,14 +104,23 @@ public class TaskUiUtil { /** * Return item to select after every combo box update. Default implementation select item, returned by {@link #getExtraItem()}. + * If returned value is not present in the list it will be added depending on policy set by {@link #addSelectedItemIfMissing()}. * * @return selected combo box item + * @see #addSelectedItemIfMissing() */ @Nullable public T getSelectedItem() { return getExtraItem(); } + /** + * @return whether value returned by {@link #getSelectedItem()} should be forcibly added to the combo box. + */ + protected boolean addSelectedItemIfMissing() { + return false; + } + @SuppressWarnings("unchecked") @Override protected void updateUI() { @@ -123,12 +137,20 @@ public class TaskUiUtil { final T selected = getSelectedItem(); if (selected != null) { if (!selected.equals(extra) && !myResult.contains(selected)) { - myComboBox.addItem(selected); + if (addSelectedItemIfMissing()) { + myComboBox.addItem(selected); + myComboBox.setSelectedItem(selected); + } + else { + selectFirstItem(); + } + } + else { + myComboBox.setSelectedItem(selected); } - myComboBox.setSelectedItem(selected); } - else if (myComboBox.getItemCount() > 0) { - myComboBox.setSelectedIndex(0); + else { + selectFirstItem(); } } else { @@ -136,13 +158,19 @@ public class TaskUiUtil { } } + private void selectFirstItem() { + if (myComboBox.getItemCount() > 0) { + myComboBox.setSelectedIndex(0); + } + } + protected void handleError() { myComboBox.removeAllItems(); } } /** - * Very simple wrapper around {@link com.intellij.ui.ListCellRendererWrapper} useful for + * Very simple wrapper around {@link ListCellRendererWrapper} useful for * combo boxes where each item has plain text representation with special message for * {@code null} value. */ diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java index e512ff04a15b..c3fc81ec27e7 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java @@ -134,14 +134,20 @@ public class ResponseUtil { if (LOG.isDebugEnabled()) { String content = getResponseContentAsString(response); TaskUtil.prettyFormatJsonToLog(LOG, content); - return myGson.fromJson(content, myClass); + return myGson.fromJson(content, myClass); + } + else { + return myGson.fromJson(getResponseContentAsReader(response), myClass); } - return myGson.fromJson(getResponseContentAsReader(response), myClass); } catch (JsonSyntaxException e) { LOG.warn("Malformed server response", e); return null; } + catch (NumberFormatException e) { + LOG.error("NFE in response: " + getResponseContentAsString(response), e); + throw new RequestFailedException("Malformed response"); + } } } @@ -175,12 +181,18 @@ public class ResponseUtil { TaskUtil.prettyFormatJsonToLog(LOG, content); return myGson.fromJson(content, myTypeToken.getType()); } - return myGson.fromJson(getResponseContentAsReader(response), myTypeToken.getType()); + else { + return myGson.fromJson(getResponseContentAsReader(response), myTypeToken.getType()); + } } catch (JsonSyntaxException e) { LOG.warn("Malformed server response", e); return Collections.emptyList(); } + catch (NumberFormatException e) { + LOG.error("NFE in response: " + getResponseContentAsString(response), e); + throw new RequestFailedException("Malformed response"); + } } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java index 89d3e3d7d8f2..e2cc5b078150 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java @@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; import com.intellij.tasks.TaskRepositoryType; @@ -35,22 +36,27 @@ import com.intellij.tasks.trello.model.TrelloCard; import com.intellij.tasks.trello.model.TrelloList; import com.intellij.tasks.trello.model.TrelloUser; import com.intellij.util.Function; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Tag; import org.apache.http.*; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.utils.URIBuilder; import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -202,7 +208,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { try { final URIBuilder url = new URIBuilder(getRestApiUrl("members", "me")) .addParameter("fields", TrelloUser.REQUIRED_FIELDS); - return makeRequestAndDeserializeJsonResponse(url.build(), TrelloUser.class); + return ObjectUtils.assertNotNull(makeRequestAndDeserializeJsonResponse(url.build(), TrelloUser.class)); } catch (Exception e) { LOG.warn("Error while fetching initial user info", e); @@ -218,7 +224,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { final URIBuilder url = new URIBuilder(getRestApiUrl("boards", id)) .addParameter("fields", TrelloBoard.REQUIRED_FIELDS); try { - return makeRequestAndDeserializeJsonResponse(url.build(), TrelloBoard.class); + return ObjectUtils.assertNotNull(makeRequestAndDeserializeJsonResponse(url.build(), TrelloBoard.class)); } catch (Exception e) { LOG.warn("Error while fetching initial board info", e); @@ -231,7 +237,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { final URIBuilder url = new URIBuilder(getRestApiUrl("lists", id)) .addParameter("fields", TrelloList.REQUIRED_FIELDS); try { - return makeRequestAndDeserializeJsonResponse(url.build(), TrelloList.class); + return ObjectUtils.assertNotNull(makeRequestAndDeserializeJsonResponse(url.build(), TrelloList.class)); } catch (Exception e) { LOG.warn("Error while fetching initial list info" + id, e); @@ -244,7 +250,12 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { if (myCurrentBoard == null || myCurrentBoard == UNSPECIFIED_BOARD) { throw new IllegalStateException("Board not set"); } - final URIBuilder url = new URIBuilder(getRestApiUrl("boards", myCurrentBoard.getId(), "lists")) + return fetchBoardLists(myCurrentBoard.getId()); + } + + @NotNull + private List fetchBoardLists(@NotNull String boardId) throws Exception { + final URIBuilder url = new URIBuilder(getRestApiUrl("boards", boardId, "lists")) .addParameter("fields", TrelloList.REQUIRED_FIELDS); return makeRequestAndDeserializeJsonResponse(url.build(), TrelloUtil.LIST_OF_LISTS_TYPE); } @@ -327,7 +338,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { return cards; } - @NotNull + @Nullable private T executeMethod(@NotNull HttpUriRequest method, @NotNull ResponseHandler handler) throws Exception { final HttpClient client = getHttpClient(); final HttpResponse response = client.execute(method); @@ -345,10 +356,11 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { @NotNull private List makeRequestAndDeserializeJsonResponse(@NotNull URI url, @NotNull TypeToken> type) throws Exception { - return executeMethod(new HttpGet(url), new GsonMultipleObjectsDeserializer(TrelloUtil.GSON, type)); + final List result = executeMethod(new HttpGet(url), new GsonMultipleObjectsDeserializer(TrelloUtil.GSON, type)); + return ObjectUtils.assertNotNull(result); } - @NotNull + @Nullable private T makeRequestAndDeserializeJsonResponse(@NotNull URI url, @NotNull Class cls) throws Exception { return executeMethod(new HttpGet(url), new GsonSingleObjectDeserializer(TrelloUtil.GSON, cls)); } @@ -424,8 +436,36 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { return "https://api.trello.com"; } + @NotNull + @Override + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + final TrelloCard card = fetchCardById(task.getId()); + if (card != null) { + final List lists = fetchBoardLists(card.getIdBoard()); + final Set result = new HashSet(); + for (TrelloList list : lists) { + if (!list.getId().equals(card.getIdList())) { + result.add(new CustomTaskState(list.getId(), list.getName())); + } + } + return result; + } + return Collections.emptySet(); + } + + @Override + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { + final URI url = new URIBuilder(getRestApiUrl("cards", task.getId(), "idList")).addParameter("value", state.getId()).build(); + final HttpResponse response = getHttpClient().execute(new HttpPut(url)); + if (response.getStatusLine() != null && + response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED && + EntityUtils.toString(response.getEntity()).trim().equals("unauthorized card permission requested")) { + throw new Exception(TaskBundle.message("trello.failure.write.access.required")); + } + } + @Override protected int getFeatures() { - return super.getFeatures() & ~NATIVE_SEARCH; + return super.getFeatures() & ~NATIVE_SEARCH | STATE_UPDATING; } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java index 0ea5905cbcb2..f7dcd54d3baa 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java @@ -260,6 +260,11 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor { @@ -284,5 +289,10 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor { public static final String DEVELOPER_KEY = "d6ec3709f7141007e150de64d4701181"; public static final String CLIENT_AUTHORIZATION_URL = - "https://trello.com/1/authorize?key=" + DEVELOPER_KEY +"&name=JetBrains&expiration=never&response_type=token"; + "https://trello.com/1/authorize?key=" + DEVELOPER_KEY +"&name=JetBrains&expiration=never&response_type=token&scope=read,write"; @NotNull @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.form deleted file mode 100644 index 8dc52a33211a..000000000000 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.form +++ /dev/null @@ -1,84 +0,0 @@ - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.java deleted file mode 100644 index fc084d293d52..000000000000 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.intellij.tasks.youtrack; - -import com.intellij.ui.components.JBLabel; -import com.intellij.util.ui.UIUtil; - -import javax.swing.*; - -/** - * @author Mikhail Golubev - */ -public class YouTrackOptionsTab { - public static final String MESSAGE = "" + - "This option should be used only when \"Name\" property for \"State\" field " + - "was changed in server settings. It's not related to localized names of states." + - ""; - - private JTextField myInProgressState; - private JTextField myResolvedState; - private JPanel myRootPanel; - private JBLabel myNoteText; - - public YouTrackOptionsTab() { - myNoteText.setComponentStyle(UIUtil.ComponentStyle.SMALL); - myNoteText.setText(MESSAGE); - } - - public JTextField getInProgressState() { - return myInProgressState; - } - - public JTextField getResolvedState() { - return myResolvedState; - } - - public JPanel getRootPanel() { - return myRootPanel; - } - - -} diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java index 5da18ef96d21..c67fa6834368 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java @@ -25,11 +25,10 @@ import com.intellij.tasks.impl.BaseRepository; import com.intellij.tasks.impl.BaseRepositoryImpl; import com.intellij.tasks.impl.LocalTaskImpl; import com.intellij.tasks.impl.TaskUtil; +import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.VersionComparatorUtil; -import com.intellij.util.xmlb.annotations.MapAnnotation; -import com.intellij.util.xmlb.annotations.Property; import com.intellij.util.xmlb.annotations.Tag; import org.apache.axis.utils.XMLChar; import org.apache.commons.httpclient.HttpClient; @@ -43,14 +42,14 @@ import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.io.InputStream; import java.io.StringReader; import java.util.Date; -import java.util.EnumMap; import java.util.List; -import java.util.Map; +import java.util.Set; /** * @author Dmitry Avdeev @@ -59,13 +58,6 @@ import java.util.Map; public class YouTrackRepository extends BaseRepositoryImpl { private String myDefaultSearch = "Assignee: me sort by: updated #Unresolved"; - private Map myCustomStateNames = new EnumMap(TaskState.class); - - // Default names for supported issues states - { - myCustomStateNames.put(TaskState.IN_PROGRESS, "In Progress"); - myCustomStateNames.put(TaskState.RESOLVED, "Fixed"); - } /** * for serialization @@ -87,7 +79,6 @@ public class YouTrackRepository extends BaseRepositoryImpl { private YouTrackRepository(YouTrackRepository other) { super(other); myDefaultSearch = other.getDefaultSearch(); - myCustomStateNames = new EnumMap(other.getCustomStateNames()); } public Task[] getIssues(@Nullable String request, int max, long since) throws Exception { @@ -98,39 +89,44 @@ public class YouTrackRepository extends BaseRepositoryImpl { } String requestUrl = "/rest/project/issues/?filter=" + encodeUrl(query) + "&max=" + max + "&updatedAfter" + since; HttpMethod method = doREST(requestUrl, false); - InputStream stream = method.getResponseBodyAsStream(); - - // todo workaround for http://youtrack.jetbrains.net/issue/JT-7984 - String s = StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET); - for (int i = 0; i < s.length(); i++) { - if (!XMLChar.isValid(s.charAt(i))) { - s = s.replace(s.charAt(i), ' '); - } - } - - Element element; try { - //InputSource source = new InputSource(stream); - //source.setEncoding("UTF-8"); - //element = new SAXBuilder(false).build(source).getRootElement(); - element = new SAXBuilder(false).build(new StringReader(s)).getRootElement(); - } - catch (JDOMException e) { - LOG.error("Can't parse YouTrack response for " + requestUrl, e); - throw e; - } - if ("error".equals(element.getName())) { - throw new Exception("Error from YouTrack for " + requestUrl + ": '" + element.getText() + "'"); - } + InputStream stream = method.getResponseBodyAsStream(); - List children = element.getChildren("issue"); - - final List tasks = ContainerUtil.mapNotNull(children, new NullableFunction() { - public Task fun(Element o) { - return createIssue(o); + // todo workaround for http://youtrack.jetbrains.net/issue/JT-7984 + String s = StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET); + for (int i = 0; i < s.length(); i++) { + if (!XMLChar.isValid(s.charAt(i))) { + s = s.replace(s.charAt(i), ' '); + } } - }); - return tasks.toArray(new Task[tasks.size()]); + + Element element; + try { + //InputSource source = new InputSource(stream); + //source.setEncoding("UTF-8"); + //element = new SAXBuilder(false).build(source).getRootElement(); + element = new SAXBuilder(false).build(new StringReader(s)).getRootElement(); + } + catch (JDOMException e) { + LOG.error("Can't parse YouTrack response for " + requestUrl, e); + throw e; + } + if ("error".equals(element.getName())) { + throw new Exception("Error from YouTrack for " + requestUrl + ": '" + element.getText() + "'"); + } + + List children = element.getChildren("issue"); + + final List tasks = ContainerUtil.mapNotNull(children, new NullableFunction() { + public Task fun(Element o) { + return createIssue(o); + } + }); + return tasks.toArray(new Task[tasks.size()]); + } + finally { + method.releaseConnection(); + } } @Nullable @@ -153,10 +149,16 @@ public class YouTrackRepository extends BaseRepositoryImpl { method.addParameter("password", getPassword()); client.getParams().setContentCharset("UTF-8"); client.executeMethod(method); - if (method.getStatusCode() != 200) { - throw new Exception("Cannot login: HTTP status code " + method.getStatusCode()); + String response; + try { + if (method.getStatusCode() != 200) { + throw new Exception("Cannot login: HTTP status code " + method.getStatusCode()); + } + response = method.getResponseBodyAsString(1000); + } + finally { + method.releaseConnection(); } - String response = method.getResponseBodyAsString(1000); if (response == null) { throw new NullPointerException(); } @@ -173,12 +175,23 @@ public class YouTrackRepository extends BaseRepositoryImpl { @Nullable public Task findTask(@NotNull String id) throws Exception { - HttpMethod method = doREST("/rest/issue/byid/" + id, false); - InputStream stream = method.getResponseBodyAsStream(); - Element element = new SAXBuilder(false).build(stream).getRootElement(); + final Element element = fetchRequestAsElement(id); return element.getName().equals("issue") ? createIssue(element) : null; } + @TestOnly + @NotNull + public Element fetchRequestAsElement(@NotNull String id) throws Exception { + final HttpMethod method = doREST("/rest/issue/byid/" + id, false); + try { + final InputStream stream = method.getResponseBodyAsStream(); + return new SAXBuilder(false).build(stream).getRootElement(); + } + finally { + method.releaseConnection(); + } + } + HttpMethod doREST(String request, boolean post) throws Exception { HttpClient client = login(new PostMethod(getUrl() + "/rest/user/login")); @@ -198,12 +211,28 @@ public class YouTrackRepository extends BaseRepositoryImpl { } @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { - String s = myCustomStateNames.get(state); - if (StringUtil.isEmpty(s)) { - s = state.name(); + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { + doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + state.getId()), true).releaseConnection(); + } + + @NotNull + @Override + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + final HttpMethod method = doREST("/rest/issue/" + task.getId() + "/execute/intellisense?command=" + encodeUrl("state "), false); + try { + final InputStream stream = method.getResponseBodyAsStream(); + final Element element = new SAXBuilder(false).build(stream).getRootElement(); + return ContainerUtil.map2Set(element.getChild("suggest").getChildren("item"), new Function() { + @Override + public CustomTaskState fun(Element element) { + final String stateName = element.getChildText("option"); + return new CustomTaskState(stateName, stateName); + } + }); + } + finally { + method.releaseConnection(); } - doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + s), true); } @Nullable @@ -315,9 +344,7 @@ public class YouTrackRepository extends BaseRepositoryImpl { public boolean equals(Object o) { if (!super.equals(o)) return false; YouTrackRepository repository = (YouTrackRepository)o; - if (!Comparing.equal(repository.getDefaultSearch(), getDefaultSearch())) return false; - if (!Comparing.equal(repository.getCustomStateNames(), getCustomStateNames())) return false; - return true; + return Comparing.equal(repository.getDefaultSearch(), getDefaultSearch()); } private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.youtrack.YouTrackRepository"); @@ -326,20 +353,30 @@ public class YouTrackRepository extends BaseRepositoryImpl { public void updateTimeSpent(@NotNull LocalTask task, @NotNull String timeSpent, @NotNull String comment) throws Exception { checkVersion(); final HttpMethod method = doREST("/rest/issue/execute/" + task.getId() + "?command=work+Today+" + timeSpent.replaceAll(" ", "+") + "+" + comment, true); - if (method.getStatusCode() != 200) { - InputStream stream = method.getResponseBodyAsStream(); - String message = new SAXBuilder(false).build(stream).getRootElement().getText(); - throw new Exception(message); + try { + if (method.getStatusCode() != 200) { + InputStream stream = method.getResponseBodyAsStream(); + String message = new SAXBuilder(false).build(stream).getRootElement().getText(); + throw new Exception(message); + } + } + finally { + method.releaseConnection(); } } private void checkVersion() throws Exception { HttpMethod method = doREST("/rest/workflow/version", false); - InputStream stream = method.getResponseBodyAsStream(); - Element element = new SAXBuilder(false).build(stream).getRootElement(); - final boolean timeTrackingAvailable = element.getName().equals("version") && VersionComparatorUtil.compare(element.getChildText("version"), "4.1") >= 0; - if (!timeTrackingAvailable) { - throw new Exception("This version of Youtrack the time tracking is not supported"); + try { + InputStream stream = method.getResponseBodyAsStream(); + Element element = new SAXBuilder(false).build(stream).getRootElement(); + final boolean timeTrackingAvailable = element.getName().equals("version") && VersionComparatorUtil.compare(element.getChildText("version"), "4.1") >= 0; + if (!timeTrackingAvailable) { + throw new Exception("This version of Youtrack the time tracking is not supported"); + } + } + finally { + method.releaseConnection(); } } @@ -347,26 +384,4 @@ public class YouTrackRepository extends BaseRepositoryImpl { protected int getFeatures() { return super.getFeatures() | TIME_MANAGEMENT | STATE_UPDATING; } - - public void setCustomStateNames(Map customStateNames) { - myCustomStateNames.putAll(customStateNames); - } - - @Tag("customStates") - @Property(surroundWithTag = false) - @MapAnnotation( - surroundWithTag = false, - keyAttributeName = "state", - valueAttributeName = "name", - surroundKeyWithTag = false, - surroundValueWithTag = false - ) - - public Map getCustomStateNames() { - return myCustomStateNames; - } - - public void setCustomStateName(TaskState state, String name) { - myCustomStateNames.put(state, name); - } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java index db16ea5247bb..34ba0a773b5c 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java @@ -3,10 +3,8 @@ package com.intellij.tasks.youtrack; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.tasks.TaskState; import com.intellij.tasks.config.BaseRepositoryEditor; import com.intellij.tasks.youtrack.lang.YouTrackLanguage; import com.intellij.ui.EditorTextField; @@ -17,14 +15,12 @@ import com.intellij.util.ui.FormBuilder; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.Map; /** * @author Dmitry Avdeev */ public class YouTrackRepositoryEditor extends BaseRepositoryEditor { private static final Logger LOG = Logger.getInstance(YouTrackRepository.class); - private final YouTrackOptionsTab myOptions; private EditorTextField myDefaultSearch; private JBLabel mySearchLabel; @@ -36,17 +32,6 @@ public class YouTrackRepositoryEditor extends BaseRepositoryEditor states = myRepository.getCustomStateNames(); - myOptions.getInProgressState().setText(StringUtil.notNullize(states.get(TaskState.IN_PROGRESS))); - myOptions.getResolvedState().setText(StringUtil.notNullize(states.get(TaskState.RESOLVED))); - - installListener(myOptions.getInProgressState()); - installListener(myOptions.getResolvedState()); - - myTabbedPane.add("Options", myOptions.getRootPanel()); } @Override @@ -61,8 +46,6 @@ public class YouTrackRepositoryEditor extends BaseRepositoryEditor states = myRepository.getAvailableTaskStates(task); + final List stateNames = ContainerUtil.map(states, new Function() { + @Override + public String fun(CustomTaskState state) { + return state.getPresentableName(); + } + }); + assertContainsElements(stateNames, "North", "South"); + + // ? -> North + myRepository.setTaskState(task, NORTH_STATE); + Element element = myRepository.fetchRequestAsElement(REQUEST_WITH_CUSTOM_STATES_ID); + assertEquals("North", element.getAttributeValue("state")); + + // North -> Submitted + myRepository.setTaskState(task, SUBMITTED_STATE); + element = myRepository.fetchRequestAsElement(REQUEST_WITH_CUSTOM_STATES_ID); + assertEquals("Submitted", element.getAttributeValue("state")); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + myRepository = new YouTrackRepository(new YouTrackRepositoryType()); + myRepository.setUrl(YOUTRACK_4_TEST_SERVER_URL); + myRepository.setUsername("buildtest"); + myRepository.setPassword("buildtest"); + } +} diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java index 654b51261d88..d9150d342ce2 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java @@ -2,8 +2,10 @@ package com.intellij.tasks.integration.live; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.trello.TrelloRepository; import com.intellij.tasks.trello.TrelloRepositoryType; +import com.intellij.tasks.trello.TrelloTask; import com.intellij.tasks.trello.model.*; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -22,8 +24,9 @@ import static com.intellij.tasks.trello.model.TrelloLabel.LabelColor.*; */ public class TrelloIntegrationTest extends LiveIntegrationTestCase { - private static final String BOARD_1_NAME = "Board 1"; - private static final String BOARD_1_ID = "53c416a8a6e5a78753562043"; + // Basic functionality (searching, filtering, etc.) + private static final String BASIC_FUNCTIONALITY_BOARD_NAME = "Basic Functionality"; + private static final String BASIC_FUNCTIONALITY_BOARD_ID = "53c416a8a6e5a78753562043"; private static final String LIST_1_1_NAME = "List 1-1"; private static final String LIST_1_1_ID = "53c416a8a6e5a78753562044"; @@ -31,6 +34,17 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase boards = myRepository.fetchUserBoards(); - assertEquals(2, boards.size()); - assertObjectsNamed("All boards of the user should be included", boards, "Board 1", "Board 2"); + assertEquals(3, boards.size()); + assertObjectsNamed("All boards of the user should be included", boards, + BASIC_FUNCTIONALITY_BOARD_NAME, LABELS_AND_COLORS_BOARD_NAME, STATE_UPDATES_BOARD_NAME); } public void testFetchListsOfBoard() throws Exception { - TrelloBoard selectedBoard = myRepository.fetchBoardById(BOARD_1_ID); + TrelloBoard selectedBoard = myRepository.fetchBoardById(BASIC_FUNCTIONALITY_BOARD_ID); assertNotNull(selectedBoard); myRepository.setCurrentBoard(selectedBoard); List lists = myRepository.fetchBoardLists(); @@ -88,7 +103,7 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase fetchCards(@Nullable String boardId, @Nullable String listId, boolean withClosed) throws Exception { if (boardId != null) { - TrelloBoard selectedBoard = myRepository.fetchBoardById(BOARD_1_ID); + TrelloBoard selectedBoard = myRepository.fetchBoardById(BASIC_FUNCTIONALITY_BOARD_ID); assertNotNull(selectedBoard); myRepository.setCurrentBoard(selectedBoard); } @@ -108,24 +123,24 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase cards = fetchCards(BOARD_1_ID, null, true); + List cards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, null, true); assertObjectsNamed("All cards of the board should be included", cards, "Card 1-1-1", "Card 1-1-2", "Card 1-2-1", "Card 1-3-1", "Archived Card"); } public void testCardsFilteringByMembership() throws Exception { myRepository.setIncludeAllCards(true); - List allCards = fetchCards(BOARD_1_ID, LIST_1_1_ID, true); + List allCards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, LIST_1_1_ID, true); assertObjectsNamed("All cards of the list should be included", allCards, "Card 1-1-1", "Card 1-1-2", "Archived Card"); myRepository.setIncludeAllCards(false); - List assignedCards = fetchCards(BOARD_1_ID, LIST_1_1_ID, true); + List assignedCards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, LIST_1_1_ID, true); assertObjectsNamed("Only cards of the list assigned to user should be included", assignedCards, "Card 1-1-1"); } public void testCardsFilteringByStatus() throws Exception { myRepository.setIncludeAllCards(true); - List allCards = fetchCards(BOARD_1_ID, LIST_1_1_NAME, true); + List allCards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, LIST_1_1_NAME, true); assertObjectsNamed("All cards of the list should be included", allCards, "Card 1-1-1", "Card 1-1-2", "Archived Card"); TrelloCard card = ContainerUtil.find(allCards, new Condition() { @@ -139,8 +154,17 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase labels = card.getLabels(); @@ -156,13 +180,41 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase states = myRepository.getAvailableTaskStates(task); + assertEquals(1, states.size()); + final CustomTaskState inProgressState = states.iterator().next(); + assertEquals(IN_PROGRESS_LIST_ID, inProgressState.getId()); + assertEquals("In Progress", inProgressState.getPresentableName()); + + // Backlog -> In Progress + myRepository.setTaskState(task, inProgressState); + card = myRepository.fetchCardById(FEATURE_CARD_ID); + assertNotNull(card); + assertEquals(STATE_UPDATES_BOARD_ID, card.getIdBoard()); + assertEquals(IN_PROGRESS_LIST_ID, card.getIdList()); + + // Discover "Backlog" list + task = new TrelloTask(card, myRepository); + states = myRepository.getAvailableTaskStates(task); + assertEquals(1, states.size()); + final CustomTaskState backlogState = states.iterator().next(); + assertEquals(BACKLOG_LIST_ID, backlogState.getId()); + assertEquals("Backlog", backlogState.getPresentableName()); + + // In Progress -> Backlog + myRepository.setTaskState(task, backlogState); + card = myRepository.fetchCardById(FEATURE_CARD_ID); + assertNotNull(card); + assertEquals(STATE_UPDATES_BOARD_ID, card.getIdBoard()); + assertEquals(BACKLOG_LIST_ID, card.getIdList()); } static void assertObjectsNamed(@NotNull String message, @NotNull Collection objects, @NotNull String... names) { diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java index f388d9d931f6..0f19c66153e5 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java @@ -27,8 +27,6 @@ import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.options.FontSize; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.containers.HashMap; import com.jediterm.pty.PtyProcessTtyConnector; import com.jediterm.terminal.TerminalColor; @@ -401,11 +399,7 @@ public class JBTerminalSystemSettingsProvider extends DefaultTabbedSettingsProvi } @Override - public void readExternal(Element element) throws InvalidDataException { - } - - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void readExternal(Element element) { } public void updateGlobalScheme(EditorColorsScheme scheme) { diff --git a/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft b/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft index 1ebebc04a62c..b60235c8f1f1 100644 --- a/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft +++ b/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft @@ -1,4 +1,5 @@ import static org.testng.Assert.*; +#parse("File Header.java") public class ${NAME} { ${BODY} } \ No newline at end of file diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java index abe744594ca7..4627efd195f0 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java @@ -65,6 +65,7 @@ import java.util.Map; */ @State( name = "Palette2", + defaultStateAsResource = true, storages = { @Storage(file = StoragePathMacros.PROJECT_FILE), @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/uiDesigner.xml", scheme = StorageScheme.DIRECTORY_BASED) diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java index 912269d3b446..1a04083a612e 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java @@ -4,59 +4,21 @@ package com.jetbrains.edu.learning.editor; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.event.EditorFactoryEvent; import com.intellij.openapi.editor.event.EditorFactoryListener; -import com.intellij.openapi.editor.event.EditorMouseAdapter; -import com.intellij.openapi.editor.event.EditorMouseEvent; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.WolfTheProblemSolver; -import com.intellij.ui.JBColor; -import com.jetbrains.edu.EduAnswerPlaceholderPainter; import com.jetbrains.edu.EduDocumentListener; -import com.jetbrains.edu.courseFormat.AnswerPlaceholder; import com.jetbrains.edu.courseFormat.TaskFile; -import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.navigation.StudyNavigator; import org.jetbrains.annotations.NotNull; -import java.awt.*; - public class StudyEditorFactoryListener implements EditorFactoryListener { - /** - * draws selected task window if there is one located in mouse position - */ - private static class WindowSelectionListener extends EditorMouseAdapter { - private final TaskFile myTaskFile; - - WindowSelectionListener(@NotNull final TaskFile taskFile) { - myTaskFile = taskFile; - } - - @Override - public void mouseClicked(EditorMouseEvent e) { - final Editor editor = e.getEditor(); - final Point point = e.getMouseEvent().getPoint(); - final LogicalPosition pos = editor.xyToLogicalPosition(point); - final AnswerPlaceholder answerPlaceholder = myTaskFile.getAnswerPlaceholder(editor.getDocument(), pos); - if (answerPlaceholder != null) { - myTaskFile.setSelectedAnswerPlaceholder(answerPlaceholder); - final Project project = editor.getProject(); - assert project != null; - final JBColor color = StudyTaskManager.getInstance(project).getColor(answerPlaceholder); - EduAnswerPlaceholderPainter.drawAnswerPlaceholder(editor, answerPlaceholder, true, color); - } - else { - StudyUtils.drawAllWindows(editor, myTaskFile); - } - } - } - @Override public void editorCreated(@NotNull final EditorFactoryEvent event) { final Editor editor = event.getEditor(); @@ -78,7 +40,6 @@ public class StudyEditorFactoryListener implements EditorFactoryListener { final TaskFile taskFile = StudyUtils.getTaskFile(project, openedFile); if (taskFile != null) { StudyNavigator.navigateToFirstAnswerPlaceholder(editor, taskFile); - editor.addEditorMouseListener(new WindowSelectionListener(taskFile)); StudyEditor.addDocumentListener(document, new EduDocumentListener(taskFile)); WolfTheProblemSolver.getInstance(project).clearProblems(openedFile); StudyUtils.drawAllWindows(editor, taskFile); diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java index 43928034db0f..bf2b59999b11 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java @@ -27,25 +27,28 @@ public class StudySmartChecker { private StudySmartChecker() { } + private static final Logger LOG = Logger.getInstance(StudySmartChecker.class); public static void smartCheck(@NotNull final AnswerPlaceholder placeholder, - @NotNull final Project project, - @NotNull final VirtualFile answerFile, - @NotNull final TaskFile answerTaskFile, - @NotNull final TaskFile usersTaskFile, - @NotNull final StudyTestRunner testRunner, - @NotNull final VirtualFile virtualFile, - @NotNull final Document usersDocument) { + @NotNull final Project project, + @NotNull final VirtualFile answerFile, + @NotNull final TaskFile answerTaskFile, + @NotNull final TaskFile usersTaskFile, + @NotNull final StudyTestRunner testRunner, + @NotNull final VirtualFile virtualFile, + @NotNull final Document usersDocument) { try { final int index = placeholder.getIndex(); + String windowCopyName = answerFile.getNameWithoutExtension() + index + EduNames.WINDOW_POSTFIX + answerFile.getExtension(); final VirtualFile windowCopy = - answerFile.copy(project, answerFile.getParent(), answerFile.getNameWithoutExtension() + index + EduNames.WINDOW_POSTFIX); + answerFile.copy(project, answerFile.getParent(), windowCopyName); final FileDocumentManager documentManager = FileDocumentManager.getInstance(); final Document windowDocument = documentManager.getDocument(windowCopy); if (windowDocument != null) { - final File resourceFile = StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask()); + final File resourceFile = + StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask()); final TaskFile windowTaskFile = new TaskFile(); TaskFile.copy(answerTaskFile, windowTaskFile); EduDocumentListener listener = new EduDocumentListener(windowTaskFile); @@ -85,5 +88,4 @@ public class StudySmartChecker { LOG.error(e); } } - } diff --git a/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java b/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java index 49921f2b37eb..25d1783f74ff 100644 --- a/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java +++ b/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java @@ -49,7 +49,6 @@ public class EduAnswerPlaceholderPainter { g.drawRect(point.x, point.y - 2, (pointEnd.x - point.x), editor.getLineHeight() + 1); } }); - editor.getCaretModel().moveToOffset(startOffset); highlighter.setGreedyToLeft(true); highlighter.setGreedyToRight(true); } diff --git a/python/educational/src/com/jetbrains/edu/EduNames.java b/python/educational/src/com/jetbrains/edu/EduNames.java index 8295735ca9d0..882a2ef9e7ef 100644 --- a/python/educational/src/com/jetbrains/edu/EduNames.java +++ b/python/educational/src/com/jetbrains/edu/EduNames.java @@ -25,7 +25,7 @@ public class EduNames { public static final String TEST_TAB_NAME = "test"; public static final String USER_TEST_INPUT = "input"; public static final String USER_TEST_OUTPUT = "output"; - public static final String WINDOW_POSTFIX = "_window.py"; + public static final String WINDOW_POSTFIX = "_window."; public static final String TASK = "task"; public static final String USER_TESTS = "userTests"; public static final String SANDBOX_DIR = "Sandbox"; diff --git a/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java b/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java index 161dc10b059b..38815badc45b 100644 --- a/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java +++ b/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java @@ -15,14 +15,18 @@ public class CourseInfo { private String myName; @SerializedName("summary") private String myDescription; + @SerializedName("course_format") + //course type in format "pycharm " + private String myType; private String myAuthor; - public static CourseInfo INVALID_COURSE = new CourseInfo("", "", ""); + public static CourseInfo INVALID_COURSE = new CourseInfo("", "", "", ""); - public CourseInfo(String name, String author, String description) { + public CourseInfo(String name, String author, String description, String type) { myName = name; myAuthor = author; myDescription = description; + myType = type; } public String getName() { @@ -37,6 +41,10 @@ public class CourseInfo { return myDescription; } + public String getType() { + return myType; + } + @Override public String toString() { return myName; diff --git a/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java b/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java index a6e45bbd7c03..56bd969aa9f8 100644 --- a/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java +++ b/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java @@ -41,6 +41,8 @@ public class EduStepicConnector { private static final String ourDomain = "stepic.org"; private static String ourSessionId = "524iethiwju2tjywaqmf7tbwx0p0jk1b"; private static String ourCSRFToken = "LJ9n6OyLVA7hxU94dlYWUu65MF51Nx37"; + //this prefix indicates that course can be opened by educational plugin + public static final String PYCHARM_PREFIX = "pycharm "; private EduStepicConnector() { } @@ -84,7 +86,8 @@ public class EduStepicConnector { course.setAuthor(info.getAuthor()); course.setDescription(info.getDescription()); course.setName(info.getName()); - course.setLanguage("Python"); // TODO: get from stepic + String courseType = info.getType(); + course.setLanguage(courseType.substring(PYCHARM_PREFIX.length())); course.setUpToDate(true); // TODO: get from stepic try { for (Integer section : info.sections) { diff --git a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java index a048894adf1a..1e8c8e24a247 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java +++ b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java @@ -104,8 +104,9 @@ public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.P @Override public void apply() throws ConfigurationException { if (myEditor == null) return; + final boolean editorWasModified = myEditor.isModified(); myEditor.apply(); - if (myModifiableModel.isChanged()) { + if (editorWasModified) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java b/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java index 28a7e082ec65..b5ccf9bd6eb7 100644 --- a/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java +++ b/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java @@ -20,10 +20,6 @@ public abstract class PythonTemplateLanguage extends Language implements Templat super(baseLanguage, ID, mimeTypes); } - protected PythonTemplateLanguage(@NotNull @NonNls final String id) { - super(id); - } - /** * @return template language readable name */ diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index cd2c6e2f0b4d..fce54b4e6581 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -98,7 +98,7 @@ public class RemoteDebugger implements ProcessDebugger { if (myConnected) { try { - myDebuggerReader = createReader(mySocket); + myDebuggerReader = createReader(); } catch (Exception e) { synchronized (mySocketObject) { @@ -231,7 +231,9 @@ public class RemoteDebugger implements ProcessDebugger { private void cleanUp() { myThreads.clear(); myResponseQueue.clear(); - mySequence = -1; + synchronized (mySequenceObject) { + mySequence = -1; + } myTempVars.clear(); } @@ -477,10 +479,10 @@ public class RemoteDebugger implements ProcessDebugger { execute(command); } - public DebuggerReader createReader(@NotNull Socket socket) throws IOException { + private DebuggerReader createReader() throws IOException { synchronized (mySocketObject) { //noinspection IOResourceOpenedButNotSafelyClosed - return new DebuggerReader(socket.getInputStream()); + return new DebuggerReader(mySocket.getInputStream()); } } @@ -488,7 +490,7 @@ public class RemoteDebugger implements ProcessDebugger { private StringBuilder myTextBuilder = new StringBuilder(); private DebuggerReader(final InputStream stream) throws IOException { - super(stream, CharsetToolkit.UTF8_CHARSET); //TODO: correct encoding? + super(stream, CharsetToolkit.UTF8_CHARSET, SleepingPolicy.BLOCKING); //TODO: correct encoding? start(); } diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java index 246e97d30ae7..c2588004329e 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java @@ -136,7 +136,6 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory myEnvironmentVariables; private String myCommandLine; private String[] myStatementsToExecute = ArrayUtil.EMPTY_STRING_ARRAY; - private ConsoleHistoryController myHistoryController; public static Key CONSOLE_KEY = new Key("PYDEV_CONSOLE_KEY"); @@ -273,7 +272,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory= myConsoleExecuteActionHandler.getPythonIndent() && - isIndentSubstring(getLanguageConsole().getEditorDocument().getText())); + isIndentSubstring(getConsoleView().getEditorDocument().getText())); } }; upAction.registerCustomShortcutSet(KeyEvent.VK_BACK_SPACE, 0, null); @@ -812,9 +811,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory + +Inspection detects locales which contain language codes not supported by Java. + + \ No newline at end of file diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 333d87167237..ded75cc64893 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -273,8 +273,6 @@ - - diff --git a/resources/src/idea/ContextViewSettings.xml b/resources/src/idea/ContextViewSettings.xml deleted file mode 100644 index 8f467b7bcd7d..000000000000 --- a/resources/src/idea/ContextViewSettings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/resources/src/idea/Debugger.xml b/resources/src/idea/Debugger.xml deleted file mode 100644 index 18ba69f6ebd7..000000000000 --- a/resources/src/idea/Debugger.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index 9efac63d0dce..149611088058 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -127,7 +127,6 @@ - @@ -166,19 +165,13 @@ - - - - - - diff --git a/resources/src/idea/UsageViewSettings.xml b/resources/src/idea/UsageViewSettings.xml deleted file mode 100644 index cc4fea038944..000000000000 --- a/resources/src/idea/UsageViewSettings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java index b41845573d7f..8cf80b20178f 100644 --- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java +++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java @@ -30,6 +30,8 @@ import com.intellij.openapi.command.CommandAdapter; import com.intellij.openapi.command.CommandEvent; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.diagnostic.Attachment; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; @@ -58,6 +60,7 @@ import java.util.Set; * @author Dennis.Ushakov */ public class XmlTagNameSynchronizer extends CommandAdapter implements ApplicationComponent { + private static final Logger LOG = Logger.getInstance(XmlTagNameSynchronizer.class); private static final Set SUPPORTED_LANGUAGES = ContainerUtil.set(HTMLLanguage.INSTANCE.getID(), XMLLanguage.INSTANCE.getID(), XHTMLLanguage.INSTANCE.getID(), @@ -76,14 +79,14 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio @Override public void editorReleased(@NotNull EditorFactoryEvent event) { - uninstallSynchronizer(event); + uninstallSynchronizer(event.getEditor()); } }, ApplicationManager.getApplication()); processor.addCommandListener(this); } - public void uninstallSynchronizer(@NotNull EditorFactoryEvent event) { - final Document document = event.getEditor().getDocument(); + public void uninstallSynchronizer(final Editor editor) { + final Document document = editor.getDocument(); final TagNameSynchronizer synchronizer = findSynchronizer(document); if (synchronizer != null) { synchronizer.clearMarkers(); @@ -91,7 +94,7 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio document.putUserData(SYNCHRONIZER_KEY, null); } - private void installSynchronizer(Editor editor) { + private void installSynchronizer(final Editor editor) { final Project project = editor.getProject(); if (project == null) return; @@ -102,7 +105,7 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio } private static Language findXmlLikeLanguage(Project project, VirtualFile file) { - final PsiFile psiFile = file != null ? PsiManager.getInstance(project).findFile(file) : null; + final PsiFile psiFile = file != null && file.isValid() ? PsiManager.getInstance(project).findFile(file) : null; if (psiFile != null) { for (Language language : psiFile.getViewProvider().getLanguages()) { if (SUPPORTED_LANGUAGES.contains(language.getID())) return language; @@ -265,12 +268,17 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio int start = -1; int end = -1; for (int i = offset - 1; i >= Math.max(0, offset - 50); i--) { - final char c = sequence.charAt(i); - if (c == '<' || (c == '/' && i > 0 && sequence.charAt(i - 1) == '<')) { - start = i + 1; - break; + try { + final char c = sequence.charAt(i); + if (c == '<' || (c == '/' && i > 0 && sequence.charAt(i - 1) == '<')) { + start = i + 1; + break; + } + if (!XmlUtil.isValidTagNameChar(c)) break; + } catch (IndexOutOfBoundsException e) { + LOG.error("incorrect offset:" + i + ", initial: " + offset, new Attachment("document.txt", sequence.toString())); + return null; } - if (!XmlUtil.isValidTagNameChar(c)) break; } if (start < 0) return null; for (int i = offset; i < Math.min(document.getTextLength(), offset + 50); i++) { diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java b/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java index f629e3216c03..795feb38fec3 100644 --- a/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java +++ b/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,10 +22,9 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.IndexableSetContributor; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import java.util.Collection; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -33,16 +32,14 @@ import java.util.Set; * @author Dmitry Avdeev */ public class ExternalResourcesRootsProvider extends IndexableSetContributor { - private final NotNullLazyValue> myStandardResources = new NotNullLazyValue>() { @NotNull @Override protected Set compute() { ExternalResourceManagerExImpl manager = (ExternalResourceManagerExImpl)ExternalResourceManager.getInstance(); - Collection> resources = manager.getStandardResources(); - Set dirs = new HashSet(); - Set set = new HashSet(); - for (Map map : resources) { + Set dirs = new THashSet(); + Set set = new THashSet(); + for (Map map : manager.getStandardResources()) { for (ExternalResourceManagerExImpl.Resource resource : map.values()) { ExternalResourceManagerExImpl.Resource dir = new ExternalResourceManagerExImpl.Resource( resource.directoryName(), resource); @@ -61,8 +58,7 @@ public class ExternalResourcesRootsProvider extends IndexableSetContributor { @Override public Set getAdditionalRootsToIndex() { - - HashSet roots = new HashSet(); + Set roots = new THashSet(); for (String url : myStandardResources.getValue()) { VirtualFile file = VfsUtilCore.findRelativeFile(url, null); if (file != null) { @@ -73,7 +69,7 @@ public class ExternalResourcesRootsProvider extends IndexableSetContributor { String path = FetchExtResourceAction.getExternalResourcesPath(); VirtualFile extResources = LocalFileSystem.getInstance().findFileByPath(path); ContainerUtil.addIfNotNull(extResources, roots); - + return roots; } } diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java index ae0f18066a14..b157a254de4e 100644 --- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java +++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java @@ -344,7 +344,7 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener> myResources = new HashMap>(); - private final Set myResourceLocations = new HashSet(); + private final Map> myResources = new THashMap>(); + private final Set myResourceLocations = new THashSet(); - private final Set myIgnoredResources = new HashSet(); + private final Set myIgnoredResources = new TreeSet(); + private final Set myStandardIgnoredResources = new TreeSet(); - private final AtomicNotNullLazyValue>> myStdResources = new AtomicNotNullLazyValue>>() { + private final NotNullLazyValue>> myStandardResources = new AtomicNotNullLazyValue>>() { @NotNull @Override protected Map> compute() { @@ -82,15 +81,14 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp protected Map> computeStdResources() { ResourceRegistrarImpl registrar = new ResourceRegistrarImpl(); - for (StandardResourceProvider provider : Extensions.getExtensions(StandardResourceProvider.EP_NAME)) { + for (StandardResourceProvider provider : StandardResourceProvider.EP_NAME.getExtensions()) { provider.registerResources(registrar); } - StandardResourceEP[] extensions = Extensions.getExtensions(StandardResourceEP.EP_NAME); - for (StandardResourceEP extension : extensions) { + for (StandardResourceEP extension : StandardResourceEP.EP_NAME.getExtensions()) { registrar.addStdResource(extension.url, extension.version, extension.resourcePath, null, extension.getLoaderForClass()); } - myIgnoredResources.addAll(registrar.getIgnored()); + myStandardIgnoredResources.addAll(registrar.getIgnored()); return registrar.getResources(); } @@ -100,7 +98,8 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp @NonNls private static final String LOCATION_ATTR = "location"; @NonNls private static final String IGNORED_RESOURCE_ELEMENT = "ignored-resource"; @NonNls private static final String HTML_DEFAULT_DOCTYPE_ELEMENT = "default-html-doctype"; - private static final String DEFAULT_VERSION = null; + + private static final String DEFAULT_VERSION = ""; @Override public boolean isStandardResource(VirtualFile file) { @@ -114,42 +113,41 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Nullable - static Map getMap(@NotNull final Map> resources, - @Nullable final String version, - final boolean create) { + static Map getMap(@NotNull Map> resources, @Nullable String version, boolean create) { + version = StringUtil.notNullize(version, DEFAULT_VERSION); Map map = resources.get(version); if (map == null) { if (create) { - map = ContainerUtil.newHashMap(); + map = new THashMap(); resources.put(version, map); } - else if (version == null || !version.equals(DEFAULT_VERSION)) { + else if (!version.equals(DEFAULT_VERSION)) { map = resources.get(DEFAULT_VERSION); } } - return map; } @Override - public String getResourceLocation(String url) { + public String getResourceLocation(@NotNull String url) { return getResourceLocation(url, DEFAULT_VERSION); } @Override - public String getResourceLocation(@NonNls String url, String version) { - String result = getUserResource(url, version); + public String getResourceLocation(@NotNull @NonNls String url, @Nullable String version) { + String result = getUserResource(url, StringUtil.notNullize(version, DEFAULT_VERSION)); if (result == null) { XMLCatalogManager manager = getCatalogManager(); if (manager != null) { result = manager.resolve(url); } - } - if (result == null) { - result = getStdResource(url, version); - } - if (result == null) { - result = url; + + if (result == null) { + result = getStdResource(url, version); + if (result == null) { + return url; + } + } } return result; } @@ -163,8 +161,8 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp @Override @Nullable - public String getStdResource(String url, String version) { - Map map = getMap(myStdResources.getValue(), version, false); + public String getStdResource(@NotNull String url, @Nullable String version) { + Map map = getMap(myStandardResources.getValue(), version, false); if (map != null) { Resource resource = map.get(url); return resource == null ? null : resource.getResourceUrl(); @@ -175,13 +173,13 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Nullable - private String getUserResource(String url, String version) { + private String getUserResource(@NotNull String url, @Nullable String version) { Map map = getMap(myResources, version, false); return map != null ? map.get(url) : null; } @Override - public String getResourceLocation(@NonNls String url, @NotNull Project project) { + public String getResourceLocation(@NotNull @NonNls String url, @NotNull Project project) { String location = getProjectResources(project).getResourceLocation(url); return location == null || location.equals(url) ? getResourceLocation(url) : location; } @@ -203,28 +201,27 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public String[] getResourceUrls(FileType fileType, final boolean includeStandard) { + public String[] getResourceUrls(FileType fileType, boolean includeStandard) { return getResourceUrls(fileType, DEFAULT_VERSION, includeStandard); } @Override - public String[] getResourceUrls(@Nullable final FileType fileType, @NonNls final String version, final boolean includeStandard) { - final List result = new LinkedList(); + public String[] getResourceUrls(@Nullable FileType fileType, @Nullable @NonNls String version, boolean includeStandard) { + List result = new LinkedList(); addResourcesFromMap(result, version, myResources); if (includeStandard) { - addResourcesFromMap(result, version, myStdResources.getValue()); + addResourcesFromMap(result, version, myStandardResources.getValue()); } return ArrayUtil.toStringArray(result); } - private static void addResourcesFromMap(final List result, - String version, - Map> resourcesMap) { + private static void addResourcesFromMap(@NotNull List result, @Nullable String version, @NotNull Map> resourcesMap) { Map resources = getMap(resourcesMap, version, false); - if (resources == null) return; - result.addAll(resources.keySet()); + if (resources != null) { + result.addAll(resources.keySet()); + } } @TestOnly @@ -249,19 +246,19 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp }); } @Override - public void addResource(String url, String location) { + public void addResource(@NotNull String url, String location) { addResource(url, DEFAULT_VERSION, location); } @Override - public void addResource(@NonNls String url, @NonNls String version, @NonNls String location) { + public void addResource(@NotNull @NonNls String url, @NonNls String version, @NonNls String location) { ApplicationManager.getApplication().assertWriteAccessAllowed(); addSilently(url, version, location); fireExternalResourceChanged(); } - private void addSilently(String url, String version, String location) { - final Map map = getMap(myResources, version, true); + private void addSilently(@NotNull String url, @Nullable String version, String location) { + Map map = getMap(myResources, version, true); assert map != null; map.put(url, location); myResourceLocations.add(location); @@ -269,12 +266,12 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public void removeResource(String url) { + public void removeResource(@NotNull String url) { removeResource(url, DEFAULT_VERSION); } @Override - public void removeResource(String url, String version) { + public void removeResource(@NotNull String url, @Nullable String version) { ApplicationManager.getApplication().assertWriteAccessAllowed(); Map map = getMap(myResources, version, false); if (map != null) { @@ -299,7 +296,7 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp @Override public String[] getAvailableUrls() { - Set urls = new HashSet(); + Set urls = new THashSet(); for (Map map : myResources.values()) { urls.addAll(map.keySet()); } @@ -327,19 +324,29 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public void addIgnoredResource(String url) { + public void addIgnoredResource(@NotNull String url) { ApplicationManager.getApplication().assertWriteAccessAllowed(); - addIgnoredSilently(url); - fireExternalResourceChanged(); + if (addIgnoredSilently(url)) { + fireExternalResourceChanged(); + } } - private void addIgnoredSilently(String url) { - myIgnoredResources.add(url); - incModificationCount(); + private boolean addIgnoredSilently(@NotNull String url) { + if (myStandardIgnoredResources.contains(url)) { + return false; + } + + if (myIgnoredResources.add(url)) { + incModificationCount(); + return true; + } + else { + return false; + } } @Override - public void removeIgnoredResource(String url) { + public void removeIgnoredResource(@NotNull String url) { ApplicationManager.getApplication().assertWriteAccessAllowed(); if (myIgnoredResources.remove(url)) { incModificationCount(); @@ -348,23 +355,38 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public boolean isIgnoredResource(String url) { - myStdResources.getValue(); // ensure ignored resources are loaded - return myIgnoredResources.contains(url) || isImplicitNamespaceDescriptor(url); + public boolean isIgnoredResource(@NotNull String url) { + if (myIgnoredResources.contains(url)) { + return true; + } + + // ensure ignored resources are loaded + myStandardResources.getValue(); + return myStandardIgnoredResources.contains(url) || isImplicitNamespaceDescriptor(url); } - private static boolean isImplicitNamespaceDescriptor(String url) { - for (ImplicitNamespaceDescriptorProvider namespaceDescriptorProvider : Extensions - .getExtensions(ImplicitNamespaceDescriptorProvider.EP_NAME)) { - if (namespaceDescriptorProvider.getNamespaceDescriptor(null, url, null) != null) return true; + private static boolean isImplicitNamespaceDescriptor(@NotNull String url) { + for (ImplicitNamespaceDescriptorProvider provider : ImplicitNamespaceDescriptorProvider.EP_NAME.getExtensions()) { + if (provider.getNamespaceDescriptor(null, url, null) != null) { + return true; + } } return false; } @Override public String[] getIgnoredResources() { - myStdResources.getValue(); // ensure ignored resources are loaded - return ArrayUtil.toStringArray(myIgnoredResources); + // ensure ignored resources are loaded + myStandardResources.getValue(); + + if (myIgnoredResources.isEmpty()) { + return ArrayUtil.toStringArray(myStandardIgnoredResources); + } + + Set set = new THashSet(myIgnoredResources.size() + myStandardIgnoredResources.size()); + set.addAll(myIgnoredResources); + set.addAll(myStandardIgnoredResources); + return ArrayUtil.toStringArray(set); } @Override @@ -372,25 +394,34 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp return getProjectResources(project).getModificationCount(); } - @Nullable @Override public Element getState() { Element element = new Element("state"); - final String[] urls = getAvailableUrls(); - for (String url : urls) { - if (url == null) continue; - String location = getResourceLocation(url); - if (location == null) continue; - final Element e = new Element(RESOURCE_ELEMENT); + Set urls = new TreeSet(); + for (Map map : myResources.values()) { + urls.addAll(map.keySet()); + } + + for (String url : urls) { + if (url == null) { + continue; + } + + String location = getResourceLocation(url); + if (location == null) { + continue; + } + + Element e = new Element(RESOURCE_ELEMENT); e.setAttribute(URL_ATTR, url); e.setAttribute(LOCATION_ATTR, location.replace(File.separatorChar, '/')); element.addContent(e); } - final String[] ignoredResources = getIgnoredResources(); - for (String ignoredResource : ignoredResources) { + myIgnoredResources.removeAll(myStandardIgnoredResources); + for (String ignoredResource : myIgnoredResources) { Element e = new Element(IGNORED_RESOURCE_ELEMENT); e.setAttribute(URL_ATTR, ignoredResource); element.addContent(e); @@ -406,30 +437,33 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp properties.setText(myCatalogPropertiesFile); element.addContent(properties); } - final ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap(); + + ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap(); PathMacrosImpl.getInstanceEx().addMacroReplacements(macroReplacements); macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive); return element; } @Override - public void loadState(Element element) { - final ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap(); + public void loadState(Element state) { + ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap(); PathMacrosImpl.getInstanceEx().addMacroExpands(macroExpands); - macroExpands.substitute(element, SystemInfo.isFileSystemCaseSensitive); + macroExpands.substitute(state, SystemInfo.isFileSystemCaseSensitive); incModificationCount(); - for (final Object o1 : element.getChildren(RESOURCE_ELEMENT)) { - Element e = (Element)o1; - addSilently(e.getAttributeValue(URL_ATTR), DEFAULT_VERSION, e.getAttributeValue(LOCATION_ATTR).replace('/', File.separatorChar)); + for (Element element : state.getChildren(RESOURCE_ELEMENT)) { + String url = element.getAttributeValue(URL_ATTR); + if (!StringUtil.isEmpty(url)) { + addSilently(url, DEFAULT_VERSION, element.getAttributeValue(LOCATION_ATTR).replace('/', File.separatorChar)); + } } - for (final Object o : element.getChildren(IGNORED_RESOURCE_ELEMENT)) { - Element e = (Element)o; - addIgnoredSilently(e.getAttributeValue(URL_ATTR)); + myIgnoredResources.clear(); + for (Element element : state.getChildren(IGNORED_RESOURCE_ELEMENT)) { + addIgnoredSilently(element.getAttributeValue(URL_ATTR)); } - Element child = element.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT); + Element child = state.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT); if (child != null) { String text = child.getText(); if (FileUtil.toSystemIndependentName(text).endsWith(".jar!/resources/html5-schema/html5.rnc")) { @@ -437,13 +471,12 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } myDefaultHtmlDoctype = text; } - Element catalogElement = element.getChild(CATALOG_PROPERTIES_ELEMENT); + Element catalogElement = state.getChild(CATALOG_PROPERTIES_ELEMENT); if (catalogElement != null) { myCatalogPropertiesFile = catalogElement.getTextTrim(); } } - @Override public void addExternalResourceListener(ExternalResourceListener listener) { myListeners.add(listener); @@ -461,10 +494,9 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } Collection> getStandardResources() { - return myStdResources.getValue().values(); + return myStandardResources.getValue().values(); } - private static final NotNullLazyKey INSTANCE_CACHE = ServiceManager.createLazyKey(ExternalResourceManagerExImpl.class); private static ExternalResourceManagerExImpl getProjectResources(Project project) { diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java b/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java index 4b9541b0ebe2..7f4a69b1847a 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,7 +15,6 @@ */ package com.intellij.javaee; -import com.intellij.application.options.PathMacrosImpl; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; @@ -29,6 +28,7 @@ import java.util.Map; */ @State(name = "ProjectResources", storages = {@Storage(file = StoragePathMacros.PROJECT_FILE)}) public class ProjectResources extends ExternalResourceManagerExImpl { + @NotNull @Override protected Map> computeStdResources() { return Collections.emptyMap(); diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java b/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java index a0fa57929f14..37462e2410b1 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.javaee; -import com.intellij.util.containers.HashMap; +import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -28,8 +28,7 @@ import java.util.Map; * @author Dmitry Avdeev */ public class ResourceRegistrarImpl implements ResourceRegistrar { - - private final Map> myResources = new HashMap>(); + private final Map> myResources = new THashMap>(); private final List myIgnored = new ArrayList(); @Override @@ -43,7 +42,7 @@ public class ResourceRegistrarImpl implements ResourceRegistrar { } public void addStdResource(@NonNls String resource, @NonNls String version, @NonNls String fileName, @Nullable Class klass, @Nullable ClassLoader classLoader) { - final Map map = ExternalResourceManagerExImpl.getMap(myResources, version, true); + Map map = ExternalResourceManagerExImpl.getMap(myResources, version, true); assert map != null; resource = new String(resource); // enforce copying; todo remove after final migration to JDK 1.7 map.put(resource, new ExternalResourceManagerExImpl.Resource(fileName, klass, classLoader)); @@ -75,10 +74,12 @@ public class ResourceRegistrarImpl implements ResourceRegistrar { addStdResource(resource, version, ExternalResourceManagerEx.STANDARD_SCHEMAS + fileName, clazz); } + @NotNull public Map> getResources() { return myResources; } + @NotNull public List getIgnored() { return myIgnored; } diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java index e86f655bc6d1..c18db0fec59d 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java @@ -15,10 +15,10 @@ */ package com.intellij.xml.impl.schema; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.FieldCache; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.util.CachedValue; @@ -85,17 +85,21 @@ public class ComplexTypeDescriptor extends TypeDescriptor { } }; + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private final FactoryMap> myAnyAttributeCache = new ConcurrentFactoryMap>() { @Override protected CachedValue create(final String key) { return CachedValuesManager.getManager(myTag.getProject()).createCachedValue(new CachedValueProvider() { @Override public Result compute() { - THashSet dependencies = new THashSet(); + THashSet dependencies = new THashSet(); CanContainAttributeType type = _canContainAttribute(key, myTag, null, new THashSet(), dependencies); if (dependencies.isEmpty()) { dependencies.add(myTag.getContainingFile()); } + if (DumbService.isDumb(myTag.getProject())) { + dependencies.add(DumbService.getInstance(myTag.getProject()).getModificationTracker()); + } return Result.create(type, ArrayUtil.toObjectArray(dependencies)); } }, false); @@ -398,7 +402,7 @@ public class ComplexTypeDescriptor extends TypeDescriptor { XmlTag tag, @Nullable String qName, Set visited, - @Nullable Set dependencies) { + @Nullable Set dependencies) { if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "anyAttribute")) { if (dependencies != null) { dependencies.add(tag.getContainingFile());