diff options
118 files changed, 1602 insertions, 535 deletions
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index bfe2f2957a9c..d857304e38f8 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -158,6 +158,8 @@ libraryLicense(name: "CGLib", libraryName: "CGLIB", version: "2.2.2", license: " libraryLicense(name: "classworlds", libraryName: "classworlds-1.1.jar", version: "1.1", license: "codehaus", url: "http://classworlds.codehaus.org/", licenseUrl: "http://classworlds.codehaus.org/license.html") libraryLicense(name: "Android SDK Tools", libraryName: "android-sdk-tools", license: "Apache 2.0", url: "http://source.android.com/") libraryLicense(name: "Android SDK Tools JPS", libraryName: "android-sdk-tools-jps", license: "Apache 2.0", url: "http://source.android.com/") +libraryLicense(name: "Android Builder", libraryName: "android-builder", license: "Apache 2.0", url: "http://source.android.com/") +libraryLicense(name: "Android Builder Model", libraryName: "builder-model", license: "Apache 2.0", url: "http://source.android.com/") libraryLicense(name: "Apache Commons BeanUtils", libraryName: "commons-beanutils.jar", version: "1.6", license: "Apache 2.0", url: "http://commons.apache.org/beanutils/") libraryLicense(name: "Apache Commons Codec", libraryName: "commons-codec", version: "1.8", license: "Apache 2.0", url: "http://commons.apache.org/codec/", licenseUrl: "http://commons.apache.org/license.html") libraryLicense(name: "Apache Commons Compress", libraryName: "commons-compress", version: "1.0", license: "Apache 2.0", url: "http://commons.apache.org/proper/commons-compress/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") @@ -195,6 +197,7 @@ libraryLicense(name: "JavaHelp", version: "2.0_02", license: "included as licens libraryLicense(name: "JCIP Annotations", libraryName: "jcip", license: "Creative Commons Attribution License", url: "http://www.jcip.net", licenseUrl: "http://creativecommons.org/licenses/by/2.5") libraryLicense(name: "JDOM", version: "1.1 (with patches by JetBrains)", license: "modified Apache", url: "http://www.jdom.org/", licenseUrl: "http://www.jdom.org/docs/faq.html#a0030") libraryLicense(name: "jgit-2.1.0", version: "2.1.0.201209190230", license: "EDL/BSD", url: "http://www.eclipse.org/jgit/", licenseUrl: "http://www.eclipse.org/org/documents/edl-v10.php", attachedTo: "git4idea") +libraryLicense(name: "javawriter", libraryName: "javawriter", license: "Apache 2.0", url: "https://github.com/square/javawriter") libraryLicense(name: "JGoodies Forms", libraryName: "jgoodies-forms", version: "1.1-preview 2006-05-04 11:55:37", license: "BSD ", url: "http://www.jgoodies.com/freeware/forms/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html") libraryLicense(name: "JGoodies Looks", libraryName: "jgoodies-looks", version: "2.4.2", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html") libraryLicense(name: "JGoodies Common", libraryName: "jgoodies-common", version: "1.2.1", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html") diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/ChunkBuild.java b/java/compiler/impl/src/com/intellij/compiler/ant/ChunkBuild.java index cd20b1c83e62..4ac5fe462571 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/ChunkBuild.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/ChunkBuild.java @@ -46,7 +46,13 @@ public class ChunkBuild extends CompositeGenerator{ } } - add(new Property(BuildProperties.getModuleChunkCompilerArgsProperty(chunk.getName()), BuildProperties.propertyRef(BuildProperties.PROPERTY_COMPILER_ADDITIONAL_ARGS)), 1); + final StringBuilder compileArgs = new StringBuilder(); + compileArgs.append(chunk.getChunkSpecificCompileOptions()); + if (compileArgs.length() > 0) { + compileArgs.append(" "); + } + compileArgs.append(BuildProperties.propertyRef(BuildProperties.PROPERTY_COMPILER_ADDITIONAL_ARGS)); + add(new Property(BuildProperties.getModuleChunkCompilerArgsProperty(chunk.getName()), compileArgs.toString()), 1); final String outputPathUrl = chunk.getOutputDirUrl(); String location = outputPathUrl != null? diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java b/java/compiler/openapi/src/com/intellij/compiler/CompilerEncodingService.java index 9c88df815466..9c88df815466 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java +++ b/java/compiler/openapi/src/com/intellij/compiler/CompilerEncodingService.java diff --git a/java/compiler/openapi/src/com/intellij/compiler/ant/ModuleChunk.java b/java/compiler/openapi/src/com/intellij/compiler/ant/ModuleChunk.java index 0665dd27dd04..c26b83038b03 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ant/ModuleChunk.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ant/ModuleChunk.java @@ -15,14 +15,21 @@ */ package com.intellij.compiler.ant; +import com.intellij.compiler.CompilerConfiguration; +import com.intellij.compiler.CompilerEncodingService; +import com.intellij.openapi.module.EffectiveLanguageLevelUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.CompilerModuleExtension; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.pom.java.LanguageLevel; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.Comparator; @@ -123,6 +130,18 @@ public class ModuleChunk { return myMainModule.getProject(); } + public String getChunkSpecificCompileOptions() { + final StringBuilder options = new StringBuilder(); + final Charset encoding = CompilerEncodingService.getInstance(getProject()).getPreferredModuleEncoding(myMainModule); + if (encoding != null) { + appendOption(options, "-encoding", encoding.name()); + } + appendOption(options, "-source", getLanguageLevelOption(EffectiveLanguageLevelUtil.getEffectiveLanguageLevel(myMainModule))); + appendOption(options, "-target", CompilerConfiguration.getInstance(getProject()).getBytecodeTargetLevel(myMainModule)); + return options.toString(); + } + + public boolean contains(final Module module) { for (Module chunkModule : myModules) { if (chunkModule.equals(module)) { @@ -131,4 +150,28 @@ public class ModuleChunk { } return false; } + + private static void appendOption(StringBuilder options, @NotNull final String name, @Nullable String value) { + if (!StringUtil.isEmpty(value)) { + if (options.length() > 0) { + options.append(" "); + } + options.append(name).append(" ").append(value); + } + } + + private static String getLanguageLevelOption(LanguageLevel level) { + if (level != null) { + switch (level) { + case JDK_1_3: return "1.3"; + case JDK_1_4: return "1.4"; + case JDK_1_5: return "1.5"; + case JDK_1_6: return "1.6"; + case JDK_1_7: return "1.7"; + case JDK_1_8: return "8"; + } + } + return null; + } + } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java index 54cef880be0f..0e33f84f01a1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java @@ -15,6 +15,7 @@ */ package com.intellij.debugger.actions; +import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.ui.breakpoints.BreakpointFactory; import com.intellij.debugger.ui.breakpoints.BreakpointPropertiesPanel; import com.intellij.debugger.ui.breakpoints.BreakpointWithHighlighter; @@ -66,6 +67,7 @@ public class JavaEditBreakpointActionHandler extends EditBreakpointActionHandler @Override public void onClosed(LightweightWindowEvent event) { propertiesPanel.saveTo(javaBreakpoint, EmptyRunnable.getInstance()); + DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().fireBreakpointChanged(javaBreakpoint); } }; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java index 408dc1aeb04e..a7b88f3b98c3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java @@ -229,6 +229,8 @@ public class DebuggerExpressionComboBox extends DebuggerEditorImpl { final EditorTextField textField = (EditorTextField)editorComponent; final Editor editor = textField.getEditor(); if (editor != null) { + int textLength = editor.getDocument().getTextLength(); + offset = Math.min(offset, textLength); textField.getCaretModel().moveToOffset(offset); editor.getSelectionModel().setSelection(offset, offset); } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java index 1c069bfccfcd..4db93153f581 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java @@ -31,6 +31,7 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Condition; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -102,10 +103,15 @@ public class SdkSettingsStep extends ModuleWizardStep { JPanel jdkPanel = new JPanel(new BorderLayout(4, 0)); jdkPanel.add(myJdkComboBox); jdkPanel.add(button, BorderLayout.EAST); - settingsStep.addSettingsField((project == null ? "Project" : "Module") + " \u001BSDK:", jdkPanel); + settingsStep.addSettingsField(getSdkFieldLabel(project), jdkPanel); } + @NotNull + protected String getSdkFieldLabel(@Nullable Project project) { + return (project == null ? "Project" : "Module") + " \u001BSDK:"; + } + @Override public JComponent getComponent() { return null; diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index d392d7a7a481..d98165f3e7a8 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -712,67 +712,8 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @NotNull private Block createMethodCallExpressionBlock(@NotNull final ASTNode node, final Wrap blockWrap, final Alignment alignment) { final ArrayList<ASTNode> nodes = new ArrayList<ASTNode>(); - final ArrayList<Block> subBlocks = new ArrayList<Block>(); collectNodes(nodes, node); - - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_CALL_CHAIN_WRAP), false); - - // We use this alignment object to align chained method calls to the first method invocation place if necessary (see IDEA-30369) - Alignment chainedCallsAlignment = createAlignment(mySettings.ALIGN_MULTILINE_CHAINED_METHODS, null); - - // We want to align chained method calls only if method target is explicitly specified, i.e. we don't want to align methods - // chain like 'recursive().recursive().recursive()' but want to align calls like 'foo.recursive().recursive().recursive()' - boolean callPointDefined = false; - List<ASTNode> lookAheadNodes = null; - boolean afterIdentifier = false; - - while (!nodes.isEmpty() || lookAheadNodes != null) { - final List<ASTNode> subNodes; - if (lookAheadNodes == null) { - subNodes = readToNextDot(nodes); - } - else { - subNodes = new ArrayList<ASTNode>(lookAheadNodes); - lookAheadNodes = null; - } - Alignment alignmentToUseForSubBlock = null; - - // Just create a no-aligned sub-block if we don't need to bother with it's alignment (either due to end-user - // setup or sub-block state). - if (chainedCallsAlignment == null || subNodes.isEmpty()) { - subBlocks.add(createSyntheticBlock(subNodes, wrap, alignmentToUseForSubBlock)); - continue; - } - - IElementType lastNodeType = subNodes.get(subNodes.size() - 1).getElementType(); - boolean currentSubBlockIsMethodCall = lastNodeType == JavaElementType.EXPRESSION_LIST; - - // Update information about chained method alignment point if necessary. I.e. we want to align only continuous method calls - // like 'foo.bar().bar().bar()' but not 'foo.bar().foo.bar()' - if (callPointDefined && !currentSubBlockIsMethodCall) { - chainedCallsAlignment = createAlignment(mySettings.ALIGN_MULTILINE_CHAINED_METHODS, null); - } - callPointDefined |= !currentSubBlockIsMethodCall; - - // We want to align method call only if call target is defined for the first chained method and current block is a method call. - if (callPointDefined && currentSubBlockIsMethodCall) { - alignmentToUseForSubBlock = chainedCallsAlignment; - } - else if (afterIdentifier && lastNodeType == JavaTokenType.IDENTIFIER) { - // Align method call to the last field access. Example: - // MyClass.staticField - // .foo(); - lookAheadNodes = readToNextDot(nodes); - if (!lookAheadNodes.isEmpty() && lookAheadNodes.get(lookAheadNodes.size() - 1).getElementType() == JavaElementType.EXPRESSION_LIST) { - alignmentToUseForSubBlock = chainedCallsAlignment; - } - } - afterIdentifier = lastNodeType == JavaTokenType.IDENTIFIER; - subBlocks.add(createSyntheticBlock(subNodes, wrap, alignmentToUseForSubBlock)); - } - - return new SyntheticCodeBlock(subBlocks, alignment, mySettings, - Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), blockWrap); + return new ChainMethodCallsBlockBuilder(alignment, blockWrap).build(nodes); } @NotNull @@ -802,19 +743,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return result; } - @NotNull - private static List<ASTNode> readToNextDot(@NotNull List<ASTNode> nodes) { - final ArrayList<ASTNode> result = new ArrayList<ASTNode>(); - result.add(nodes.remove(0)); - for (Iterator<ASTNode> iterator = nodes.iterator(); iterator.hasNext();) { - ASTNode node = iterator.next(); - if (node.getElementType() == JavaTokenType.DOT) break; - result.add(node); - iterator.remove(); - } - return result; - } - private static void collectNodes(@NotNull List<ASTNode> nodes, @NotNull ASTNode node) { ASTNode child = node.getFirstChildNode(); while (child != null) { @@ -1504,4 +1432,105 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(childrenIndent), null)); return result; } + + private class ChainMethodCallsBlockBuilder { + private Wrap blockWrap; + private Alignment blockAlignment; + + private Wrap myWrap; + private Alignment myChainedCallsAlignment; + + public ChainMethodCallsBlockBuilder(Alignment alignment, Wrap wrap) { + blockWrap = wrap; + blockAlignment = alignment; + } + + public Block build(List<ASTNode> nodes) { + myWrap = getNewWrap(); + myChainedCallsAlignment = getNewAlignment(); + + List<Block> blocks = buildBlocksFrom(nodes); + Indent indent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS); + + return new SyntheticCodeBlock(blocks, blockAlignment, mySettings, indent, blockWrap); + } + + private List<Block> buildBlocksFrom(List<ASTNode> nodes) { + List<ChainedCallChunk> methodCall = splitMethodCallOnChunksByDots(nodes); + Wrap wrapToUse = null; + Alignment alignmentToUse = null; + + List<Block> blocks = new ArrayList<Block>(); + + for (ChainedCallChunk currentCallChunk : methodCall) { + if (isMethodCall(currentCallChunk)) { + wrapToUse = myWrap; + alignmentToUse = shouldAlignMethod(currentCallChunk, methodCall) ? myChainedCallsAlignment : null; + } + else if (wrapToUse != null) { + wrapToUse = null; + alignmentToUse = null; + + myChainedCallsAlignment = getNewAlignment(); + myWrap = getNewWrap(); + } + + blocks.add(createSyntheticBlock(currentCallChunk.nodes, wrapToUse, alignmentToUse)); + } + + return blocks; + } + + private boolean shouldAlignMethod(ChainedCallChunk currentMethodChunk, List<ChainedCallChunk> methodCall) { + return mySettings.ALIGN_MULTILINE_CHAINED_METHODS + && !currentMethodChunk.isEmpty() + && !chunkIsFirstInChainMethodCall(currentMethodChunk, methodCall); + } + + private boolean chunkIsFirstInChainMethodCall(@NotNull ChainedCallChunk callChunk, @NotNull List<ChainedCallChunk> methodCall) { + return !methodCall.isEmpty() && callChunk == methodCall.get(0); + } + + @NotNull + private List<ChainedCallChunk> splitMethodCallOnChunksByDots(@NotNull List<ASTNode> nodes) { + List<ChainedCallChunk> result = new ArrayList<ChainedCallChunk>(); + + List<ASTNode> current = new ArrayList<ASTNode>(); + for (ASTNode node : nodes) { + if (node.getElementType() == JavaTokenType.DOT) { + result.add(new ChainedCallChunk(current)); + current = new ArrayList<ASTNode>(); + } + current.add(node); + } + + result.add(new ChainedCallChunk(current)); + return result; + } + + private Alignment getNewAlignment() { + return createAlignment(mySettings.ALIGN_MULTILINE_CHAINED_METHODS, null); + } + + private Wrap getNewWrap() { + return Wrap.createWrap(getWrapType(mySettings.METHOD_CALL_CHAIN_WRAP), false); + } + + private boolean isMethodCall(@NotNull ChainedCallChunk callChunk) { + List<ASTNode> nodes = callChunk.nodes; + return !nodes.isEmpty() && nodes.get(nodes.size() - 1).getElementType() == JavaElementType.EXPRESSION_LIST; + } + } + + private static class ChainedCallChunk { + @NotNull final List<ASTNode> nodes; + + ChainedCallChunk(@NotNull List<ASTNode> nodes) { + this.nodes = nodes; + } + + boolean isEmpty() { + return nodes.isEmpty(); + } + } } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 8f090b072d16..eed6d597e476 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -840,8 +840,14 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } else { if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE, null, - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + PsiElement branch = statement.getElseBranch(); + boolean shouldKeepInOneLine = mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE + && branch != null + && !branch.textContains('\n'); + + myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE, + mySettings.BRACE_STYLE, + null, shouldKeepInOneLine, true); } else { createSpacingBeforeElementInsideControlStatement(); @@ -849,10 +855,19 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } } else if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { - boolean space = myRole2 == ChildRole.ELSE_BRANCH ? mySettings.SPACE_BEFORE_ELSE_LBRACE : mySettings.SPACE_BEFORE_IF_LBRACE; + boolean space = myRole2 == ChildRole.ELSE_BRANCH ? mySettings.SPACE_BEFORE_ELSE_LBRACE + : mySettings.SPACE_BEFORE_IF_LBRACE; + + PsiElement branch = myRole2 == ChildRole.ELSE_BRANCH ? statement.getElseBranch() + : statement.getThenBranch(); + + boolean shouldKeepInOneLine = mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE + && branch != null + && !branch.textContains('\n'); + myResult = getSpaceBeforeLBrace(space, mySettings.BRACE_STYLE, new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + shouldKeepInOneLine, true); } else if (myRole2 == ChildRole.LPARENTH) { createSpaceInCode(mySettings.SPACE_BEFORE_IF_PARENTHESES); @@ -909,7 +924,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { else if (braceStyle == CommonCodeStyleSettings.END_OF_LINE || braceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) { return createNonLFSpace(space, null, false); } - else if (braceStyle == CommonCodeStyleSettings.NEXT_LINE && !mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE) { + else if (braceStyle == CommonCodeStyleSettings.NEXT_LINE) { space = (keepOneLine && spaceBeforeLbrace) ? 1 : 0; return Spacing.createSpacing(space, 0, keepOneLine ? 0 : 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); } @@ -917,9 +932,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { TextRange dependencyRangeToUse = dependantRange == null || useParentBlockAsDependencyAllTheTime ? myParent.getTextRange() : dependantRange; - return Spacing.createDependentLFSpacing( - space, space, dependencyRangeToUse, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE - ); + return Spacing.createDependentLFSpacing(space, space, dependencyRangeToUse, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); } else { return Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); @@ -1043,8 +1056,12 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { ASTNode dependencyEndAnchor = mySettings.METHOD_BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE ? myChild2 : myChild1; int dependencyEnd = dependencyEndAnchor.getTextRange().getEndOffset(); + boolean keepInOneLine = mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE + && method.getBody() != null + && !method.getBody().textContains('\n'); + myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, - new TextRange(dependencyStart, dependencyEnd), mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE, + new TextRange(dependencyStart, dependencyEnd), keepInOneLine, useParentBlockAsDependencyAllTheTime); } else if (myRole1 == ChildRole.MODIFIER_LIST) { 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 96930ebe4f97..30b9a2b091bd 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -21,8 +21,6 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.*; import com.intellij.util.Function; -import com.sun.tools.javac.code.Kinds; -import com.sun.tools.javac.tree.TreeInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java index 43c4036ef814..87b664d9bfe3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java +++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java @@ -20,7 +20,6 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.compiled.ClsFileImpl; import org.jetbrains.annotations.NotNull; @@ -40,20 +39,23 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider { protected PsiFile createFile(@NotNull final Project project, @NotNull final VirtualFile vFile, @NotNull final FileType fileType) { final FileIndexFacade fileIndex = ServiceManager.getService(project, FileIndexFacade.class); if (fileIndex.isInLibraryClasses(vFile) || !fileIndex.isInSource(vFile)) { - String name = vFile.getName(); - - // skip inners & anonymous (todo: read actual class name from file) - int dotIndex = name.lastIndexOf('.'); - if (dotIndex < 0) dotIndex = name.length(); - int index = name.lastIndexOf('$', dotIndex); - if (index <= 0 || index == dotIndex - 1) { - return new ClsFileImpl((PsiManagerImpl)PsiManager.getInstance(project), this); + if (!isInnerOrAnonymousClass(vFile)) { + return new ClsFileImpl(PsiManager.getInstance(project), this); } } return null; } + public static boolean isInnerOrAnonymousClass(VirtualFile file) { + // todo: read actual class name from file + String name = file.getName(); + int dotIndex = name.lastIndexOf('.'); + if (dotIndex < 0) dotIndex = name.length(); + int index = name.lastIndexOf('$', dotIndex); + return index > 0 && index != dotIndex - 1; + } + @NotNull @Override public SingleRootFileViewProvider createCopy(@NotNull final VirtualFile copy) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java index 68e5b0f02ec7..43b57aa4e607 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java @@ -26,16 +26,25 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.util.cls.ClsFormatException; import com.intellij.util.indexing.FileContent; +import java.util.*; + /** * @author max */ public class ClassFileStubBuilder implements BinaryFileStubBuilder { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClassFileStubBuilder"); - public static final int STUB_VERSION = JavaFileElementType.STUB_VERSION + 6; + + public static final int STUB_VERSION = 7 + JavaFileElementType.STUB_VERSION; @Override public boolean acceptsFile(final VirtualFile file) { - return true; + final ClsStubBuilderFactory[] factories = Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME); + for (ClsStubBuilderFactory factory : factories) { + if (!factory.isInnerClass(file)) { + return true; + } + } + return false; } @Override @@ -63,6 +72,18 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder { @Override public int getStubVersion() { - return STUB_VERSION; + int version = STUB_VERSION; + List<ClsStubBuilderFactory> factories = new ArrayList<ClsStubBuilderFactory>(Arrays.asList( + Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME))); + Collections.sort(factories, new Comparator<ClsStubBuilderFactory>() { // stable order in copy + @Override + public int compare(ClsStubBuilderFactory o1, ClsStubBuilderFactory o2) { + return o1.getClass().getName().compareTo(o2.getClass().getName()); + } + }); + for(ClsStubBuilderFactory factory:factories) { + version = version * 31 + factory.getStubVersion() + factory.getClass().getName().hashCode(); + } + return version; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.java index 49cdf57e379d..b670938bbfd5 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.java @@ -47,4 +47,6 @@ public abstract class ClsStubBuilderFactory<T extends PsiFile> { * @return false in case if it's not inner class */ public abstract boolean isInnerClass(final VirtualFile file); + + public int getStubVersion() { return 1; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/DefaultClsStubBuilderFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/DefaultClsStubBuilderFactory.java index dd1f0e44ef5d..db75c582cca5 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/DefaultClsStubBuilderFactory.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/DefaultClsStubBuilderFactory.java @@ -18,6 +18,7 @@ package com.intellij.psi.impl.compiled; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.ClassFileViewProvider; import com.intellij.psi.PsiClass; import com.intellij.psi.impl.java.stubs.PsiClassStub; import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; @@ -68,16 +69,7 @@ public class DefaultClsStubBuilderFactory extends ClsStubBuilderFactory { @Override public boolean isInnerClass(VirtualFile file) { - String name = file.getNameWithoutExtension(); - int len = name.length(); - int idx = name.indexOf('$'); - - while (idx > 0) { - if (idx + 1 < len && Character.isDigit(name.charAt(idx + 1))) return true; - idx = name.indexOf('$', idx + 1); - } - - return false; + return ClassFileViewProvider.isInnerOrAnonymousClass(file); } private static class VirtualFileInnerClassStrategy implements InnerClassSourceStrategy<VirtualFile> { diff --git a/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment.java b/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment.java index 47c1abe3b84f..b825cbfdc784 100644 --- a/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment.java +++ b/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment.java @@ -23,7 +23,6 @@ class FormattingTest { instanceFoo.instanceMethodWithQuiteLongNameIndeed().staticMethodWithQuiteLongNameIndeed() .instanceFoo.instanceMethodWithQuiteLongNameIndeed().staticMethodWithQuiteLongNameIndeed().instanceMethodWithQuiteLongNameIndeed(); - // Chained calls with implicit target - method calls are not aligned and use continuation indent instead. instanceMethodWithQuiteLongNameIndeed().instanceMethodWithQuiteLongNameIndeed().instanceMethodWithQuiteLongNameIndeed().instanceMethodWithQuiteLongNameIndeed(); } diff --git a/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment_after.java b/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment_after.java index 0b21b924963a..4d9f05f7f258 100644 --- a/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment_after.java +++ b/java/java-tests/testData/psi/formatter/java/ChainedMethodsAlignment_after.java @@ -31,9 +31,9 @@ class FormattingTest { .instanceFoo.instanceMethodWithQuiteLongNameIndeed().staticMethodWithQuiteLongNameIndeed() .instanceMethodWithQuiteLongNameIndeed(); - // Chained calls with implicit target - method calls are not aligned and use continuation indent instead. instanceMethodWithQuiteLongNameIndeed().instanceMethodWithQuiteLongNameIndeed() - .instanceMethodWithQuiteLongNameIndeed().instanceMethodWithQuiteLongNameIndeed(); + .instanceMethodWithQuiteLongNameIndeed() + .instanceMethodWithQuiteLongNameIndeed(); } public FormattingTest instanceMethodWithQuiteLongNameIndeed() { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy index 183036b63e45..f294f865fd24 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -15,13 +15,13 @@ */ package com.intellij.codeInsight.editorActions -import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest +import com.intellij.openapi.editor.impl.AbstractEditorTest /** * @author Denis Zhdanov * @since 9/20/12 6:17 PM */ -class FixDocCommentTest extends AbstractEditorProcessingOnDocumentModificationTest { +class FixDocCommentTest extends AbstractEditorTest { void testGenerateMethodDoc() { doTest( diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/SelectionQuotingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/SelectionQuotingTest.groovy index 1c492325eb3c..fd7ffc5d9c79 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/SelectionQuotingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/SelectionQuotingTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -15,7 +15,7 @@ */ package com.intellij.codeInsight.editorActions -import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest +import com.intellij.openapi.editor.impl.AbstractEditorTest import com.intellij.testFramework.TestFileType import com.intellij.codeInsight.CodeInsightSettings @@ -23,7 +23,7 @@ import com.intellij.codeInsight.CodeInsightSettings * @author Denis Zhdanov * @since 7/14/11 2:15 PM */ -class SelectionQuotingTest extends AbstractEditorProcessingOnDocumentModificationTest { +class SelectionQuotingTest extends AbstractEditorTest { void testBuggySelection() { diff --git a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingProcessingOnDocumentModificationTest.java b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingProcessingOnDocumentModificationTest.java index 6764d070b20d..6da536d86d2c 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingProcessingOnDocumentModificationTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingProcessingOnDocumentModificationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -26,7 +26,7 @@ import java.io.IOException; * @author Denis Zhdanov * @since 11/18/10 7:42 PM */ -public class FoldingProcessingOnDocumentModificationTest extends AbstractEditorProcessingOnDocumentModificationTest { +public class FoldingProcessingOnDocumentModificationTest extends AbstractEditorTest { public void testUnexpectedClassLevelJavadocExpandingOnClassSignatureChange() throws IOException { // Inspired by IDEA-61275 diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java index 79537e097c43..c0902414d277 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java @@ -44,7 +44,7 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest { "Holder.INSTANCE\n" + " .foo();", "Holder.INSTANCE\n" + - " .foo();" + " .foo();" ); } @@ -301,4 +301,93 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest { "try (MyResource r1 = null;\n" + " MyResource r2 = null) { }"); } + + + public void testChainedMethodCallsAfterFieldsChain_WithAlignment() throws Exception { + getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true; + getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS; + + doMethodTest( + "a.current.current.current.getThis().getThis().getThis();", + + "a.current.current.current.getThis()\n" + + " .getThis()\n" + + " .getThis();" + ); + + doMethodTest( + "a.current.current.current.getThis().getThis().getThis().current.getThis().getThis().getThis().getThis();", + + "a.current.current.current.getThis()\n" + + " .getThis()\n" + + " .getThis().current.getThis()\n" + + " .getThis()\n" + + " .getThis()\n" + + " .getThis();" + ); + + + String onlyMethodCalls = "getThis().getThis().getThis();"; + String formatedMethodCalls = "getThis().getThis()\n" + + " .getThis();"; + + doMethodTest(onlyMethodCalls, formatedMethodCalls); + } + + public void testChainedMethodCallsAfterFieldsChain_WithoutAlignment() throws Exception { + getSettings().ALIGN_MULTILINE_CHAINED_METHODS = false; + getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS; + + doMethodTest( + "a.current.current.current.getThis().getThis().getThis();", + + "a.current.current.current.getThis()\n" + + " .getThis()\n" + + " .getThis();" + ); + } + + public void testChainedMethodCalls_WithChopDownIfLongOption() throws Exception { + getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true; + getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM; // it's equal to "Chop down if long" + getSettings().getRootSettings().RIGHT_MARGIN = 50; + + String before = "a.current.current.getThis().getThis().getThis().getThis().getThis();"; + doMethodTest( + before, + "a.current.current.getThis()\n" + + " .getThis()\n" + + " .getThis()\n" + + " .getThis()\n" + + " .getThis();" + ); + + getSettings().getRootSettings().RIGHT_MARGIN = 80; + doMethodTest(before, before); + } + + public void testChainedMethodCalls_WithWrapIfNeededOption() throws Exception { + getSettings().ALIGN_MULTILINE_CHAINED_METHODS = false; + getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; + getSettings().getRootSettings().RIGHT_MARGIN = 50; + + String before = "a.current.current.getThis().getThis().getThis().getThis();"; + + doMethodTest( + before, + "a.current.current.getThis().getThis()\n" + + " .getThis().getThis();" + ); + + getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true; + + doMethodTest( + before, + "a.current.current.getThis().getThis()\n" + + " .getThis().getThis();" + ); + + getSettings().getRootSettings().RIGHT_MARGIN = 75; + doMethodTest(before, before); + } } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java index 2e2d0c5943e3..52dc555c981b 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java @@ -165,4 +165,81 @@ public class JavaFormatterBracesTest extends AbstractJavaFormatterTest { doTextTest(text, text); } + public void testKeepSimpleBlocksInOneLine_OnIfStatementsThenBlock() throws Exception { + getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true; + String singleLine = "if (2 > 3) { System.out.println(\"AA!\"); }"; + + getSettings().BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; + doMethodTest(singleLine, singleLine); + + getSettings().BRACE_STYLE = CommonCodeStyleSettings.END_OF_LINE; + doMethodTest(singleLine, singleLine); + } + + public void testKeepSimpleBlocksInOneLine_OnIfStatementsElseBlock() throws Exception { + getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true; + + String before = "if (2 > 3) {\n" + + " System.out.println(\"AA!\");\n" + + "} else { int a = 3; }"; + + String afterNextLineOption = "if (2 > 3)\n" + + "{\n" + + " System.out.println(\"AA!\");\n" + + "} else { int a = 3; }"; + + getSettings().BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; + doMethodTest(before, afterNextLineOption); + + getSettings().BRACE_STYLE = CommonCodeStyleSettings.END_OF_LINE; + doMethodTest(before, before); + } + + public void testIfStatement_WhenBraceOnNextLine_AndKeepSimpleBlockInOneLineEnabled() throws Exception { + getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true; + getSettings().BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; + String before = "if (2 > 3) {\n" + + " System.out.println(\"AA!\");\n" + + "}"; + String after = "if (2 > 3)\n" + + "{\n" + + " System.out.println(\"AA!\");\n" + + "}"; + doMethodTest(before, after); + } + + public void testIfStatementElseBranchIsOnNewLine() throws Exception { + getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true; + getSettings().BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; + String before = "if (2 > 3) {\n" + + " System.out.println(\"AA!\");\n" + + "} else {\n" + + " int a = 3;\n" + + "}"; + String after = "if (2 > 3)\n" + + "{\n" + + " System.out.println(\"AA!\");\n" + + "} else\n" + + "{\n" + + " int a = 3;\n" + + "}"; + doMethodTest(before, after); + } + + public void testIfElseBranchesKeepedInOneLine() throws Exception { + getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true; + getSettings().BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; + + String singleLine = "if (2 > 3) { System.out.println(\"AA!\"); } else { System.out.println(\"BBB!!\"); }"; + String multiLine = "if (2 > 3) { System.out.println(\"AA!\"); }\n" + + "else { System.out.println(\"BBB!!\"); }"; + + getSettings().ELSE_ON_NEW_LINE = false; + doMethodTest(singleLine, singleLine); + doMethodTest(multiLine, singleLine); + + getSettings().ELSE_ON_NEW_LINE = true; + doMethodTest(singleLine, multiLine); + doMethodTest(multiLine, multiLine); + } } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java index 8adb06b24d19..b9b652d92417 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java @@ -2195,8 +2195,12 @@ public void testSCR260() throws Exception { getSettings().KEEP_SIMPLE_METHODS_IN_ONE_LINE = true; getSettings().ALIGN_MULTILINE_PARAMETERS = true; getSettings().METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED; - doTextTest("class TEst {\n" + "void foo(A a,B b){ /* compiled code */ }\n" + "}", - "class TEst {\n" + " void foo(A a, B b)\n" + " { /* compiled code */ }\n" + "}"); + doTextTest("class TEst {\n" + + " void foo(A a,B b){ /* compiled code */ }\n" + + "}", + "class TEst {\n" + + " void foo(A a,\n" + + " B b) { /* compiled code */ }\n" + "}"); } public void testSCR1615() throws Exception { diff --git a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCaseUtil.java b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCaseUtil.java new file mode 100644 index 000000000000..aa77a1e03473 --- /dev/null +++ b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCaseUtil.java @@ -0,0 +1,39 @@ +/* + * 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; + +import com.intellij.codeInsight.actions.CodeInsightAction; +import com.intellij.ide.DataManager; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.AnActionEvent; + +public class CodeInsightTestCaseUtil { + public static void doAction(CodeInsightTestCase testCase, CodeInsightAction action, String testName, String ext) throws Exception { + testCase.configureByFile(testName + "." + ext); + + action.actionPerformed(new AnActionEvent( + null, + DataManager.getInstance().getDataContext(), + "", + action.getTemplatePresentation(), + ActionManager.getInstance(), + 0) + ); + + testCase.checkResultByFile(testName + "_after." + ext); + } + +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java index 49f0cf7649ba..ab928c0511f1 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildOutputConsumer.java @@ -15,13 +15,29 @@ */ package org.jetbrains.jps.builders; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.io.IOException; import java.util.Collection; /** + * Use methods of this interface to register files produced by a builder in the build system. This will allow other builders to process + * generated files and also update the source-to-output mapping. The build system deletes output files corresponding to changed or deleted + * source files before the next build starts. Also all output files registered in the mapping are cleared on forced recompilation (rebuild). + * * @author nik */ public interface BuildOutputConsumer { - void registerOutputFile(File outputFile, Collection<String> sourcePaths) throws IOException; + /** + * Notifies the build system that {@code outputFile} was produced from {@code sourcePaths}. + */ + void registerOutputFile(@NotNull File outputFile, @NotNull Collection<String> sourcePaths) throws IOException; + + /** + * Notifies the build system that the entire contents of {@code outputDir} was produced from {@code sourcePaths}. Note that + * if one of {@code sourcePaths} changes after the build is finished the {@code outputDir} will be deleted completely before + * the next build starts so don't use this method if {@code outputDir} contains source files or files produced by other builders. + */ + void registerOutputDirectory(@NotNull File outputDir, @NotNull Collection<String> sourcePaths) throws IOException; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java index 5b0cf20e33be..8cacef7908a1 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildOutputConsumerImpl.java @@ -15,12 +15,16 @@ */ package org.jetbrains.jps.builders.impl; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.BuildOutputConsumer; import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.storage.SourceToOutputMapping; import org.jetbrains.jps.incremental.CompileContext; +import org.jetbrains.jps.incremental.ModuleBuildTarget; +import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget; import org.jetbrains.jps.incremental.messages.FileGeneratedEvent; import java.io.File; @@ -32,6 +36,7 @@ import java.util.Collection; * Date: 11/16/12 */ public class BuildOutputConsumerImpl implements BuildOutputConsumer { + private static final Logger LOG = Logger.getInstance(BuildOutputConsumerImpl.class); private final BuildTarget<?> myTarget; private final CompileContext myContext; private FileGeneratedEvent myFileGeneratedEvent; @@ -45,28 +50,57 @@ public class BuildOutputConsumerImpl implements BuildOutputConsumer { myOutputs = myTarget.getOutputRoots(context); } - @Override - public void registerOutputFile(final File outputFile, Collection<String> sourcePaths) throws IOException { - final String outputFilePath = FileUtil.toSystemIndependentName(outputFile.getPath()); + private void registerOutput(final File output, boolean isDirectory, Collection<String> sourcePaths) throws IOException { + final String outputPath = FileUtil.toSystemIndependentName(output.getPath()); for (File outputRoot : myOutputs) { - String outputRootPath = FileUtil.toSystemIndependentName(outputRoot.getPath()); - final String relativePath = FileUtil.getRelativePath(outputRootPath, outputFilePath, '/'); + final String outputRootPath = FileUtil.toSystemIndependentName(outputRoot.getPath()); + final String relativePath = FileUtil.getRelativePath(outputRootPath, outputPath, '/'); if (relativePath != null && !relativePath.startsWith("../")) { // the relative path must be under the root or equal to it - myFileGeneratedEvent.add(outputRootPath, relativePath); + if (isDirectory) { + addEventsRecursively(output, outputRootPath, relativePath); + } + else { + myFileGeneratedEvent.add(outputRootPath, relativePath); + } } } final SourceToOutputMapping mapping = myContext.getProjectDescriptor().dataManager.getSourceToOutputMap(myTarget); for (String sourcePath : sourcePaths) { if (myRegisteredSources.add(FileUtil.toSystemIndependentName(sourcePath))) { - mapping.setOutput(sourcePath, outputFilePath); + mapping.setOutput(sourcePath, outputPath); } else { - mapping.appendOutput(sourcePath, outputFilePath); + mapping.appendOutput(sourcePath, outputPath); + } + } + } + + private void addEventsRecursively(File output, String outputRootPath, String relativePath) { + File[] children = output.listFiles(); + if (children == null) { + myFileGeneratedEvent.add(outputRootPath, relativePath); + } + else { + String prefix = relativePath.isEmpty() || relativePath.equals(".") ? "" : relativePath + "/"; + for (File child : children) { + addEventsRecursively(child, outputRootPath, prefix + child.getName()); } } } + @Override + public void registerOutputFile(@NotNull final File outputFile, @NotNull Collection<String> sourcePaths) throws IOException { + registerOutput(outputFile, false, sourcePaths); + } + + @Override + public void registerOutputDirectory(@NotNull File outputDir, @NotNull Collection<String> sourcePaths) throws IOException { + LOG.assertTrue(!(myTarget instanceof ModuleBuildTarget) && !(myTarget instanceof ArtifactBuildTarget), + "'registerOutputDirectory' method cannot be used for target " + myTarget + ", it will break incremental compilation"); + registerOutput(outputDir, true, sourcePaths); + } + public void fireFileGeneratedEvent() { if (!myFileGeneratedEvent.getPaths().isEmpty()) { myContext.processMessage(myFileGeneratedEvent); diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java index 7061fc649300..c4928a05dfe6 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java @@ -185,7 +185,7 @@ public class BuildRunner { } } if (includeDependenciesToScope) { - includeDependenciesToScope(targetTypes, targets, pd); + includeDependenciesToScope(targetTypes, targets, targetTypesToForceBuild, pd); } final Timestamps timestamps = pd.timestamps.getStorage(); @@ -215,7 +215,7 @@ public class BuildRunner { } private static void includeDependenciesToScope(Set<BuildTargetType<?>> targetTypes, Set<BuildTarget<?>> targets, - ProjectDescriptor descriptor) { + Set<BuildTargetType<?>> targetTypesToForceBuild, ProjectDescriptor descriptor) { //todo[nik] get rid of CompileContext parameter for BuildTargetIndex.getDependencies() and use it here TargetOutputIndex dummyIndex = new TargetOutputIndex() { @Override @@ -231,6 +231,9 @@ public class BuildRunner { for (BuildTarget<?> depTarget : target.computeDependencies(descriptor.getBuildTargetIndex(), dummyIndex)) { if (!targets.contains(depTarget) && !targetTypes.contains(depTarget.getTargetType())) { next.add(depTarget); + if (targetTypesToForceBuild.contains(target.getTargetType())) { + targetTypesToForceBuild.add(depTarget.getTargetType()); + } } } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java index 07d424d4f9b3..1a25b32c3bbd 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java @@ -18,6 +18,7 @@ package org.jetbrains.jps.incremental; import com.intellij.openapi.util.io.FileUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.impl.BuildOutputConsumerImpl; import org.jetbrains.jps.builders.impl.BuildTargetChunk; @@ -169,17 +170,7 @@ public class BuildOperations { if (outputs != null) { final boolean shouldPruneOutputDirs = target instanceof ModuleBasedTarget; for (String output : outputs) { - final File outFile = new File(output); - final boolean deleted = outFile.delete(); - if (deleted) { - deletedPaths.add(output); - if (shouldPruneOutputDirs) { - final File parent = outFile.getParentFile(); - if (parent != null) { - dirsToDelete.add(parent); - } - } - } + deleteRecursively(output, deletedPaths, shouldPruneOutputDirs ? dirsToDelete : null); } Set<File> cleaned = cleanedSources.get(target); if (cleaned == null) { @@ -190,6 +181,7 @@ public class BuildOperations { } return true; } + }); if (context.isMake()) { @@ -211,4 +203,30 @@ public class BuildOperations { throw new ProjectBuildException(e); } } + + public static boolean deleteRecursively(@NotNull String path, @NotNull Collection<String> deletedPaths, @Nullable Set<File> parentDirs) { + File file = new File(path); + boolean deleted = deleteRecursively(file, deletedPaths); + if (deleted && parentDirs != null) { + File parent = file.getParentFile(); + if (parent != null) { + parentDirs.add(parent); + } + } + return deleted; + } + + private static boolean deleteRecursively(File file, Collection<String> deletedPaths) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + deleteRecursively(child, deletedPaths); + } + } + boolean deleted = file.delete(); + if (deleted && children == null) { + deletedPaths.add(FileUtil.toSystemIndependentName(file.getPath())); + } + return deleted; + } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 522e1c5e2653..7ac1a3799946 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -401,25 +401,19 @@ public class IncProjectBuilder { private void cleanOutputRoots(CompileContext context) throws ProjectBuildException { // whole project is affected - ProjectDescriptor projectDescriptor = context.getProjectDescriptor(); - JpsJavaCompilerConfiguration configuration = - JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(projectDescriptor.getProject()); + final ProjectDescriptor projectDescriptor = context.getProjectDescriptor(); + final JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(projectDescriptor.getProject()); final boolean shouldClear = configuration.isClearOutputDirectoryOnRebuild(); - try { - if (shouldClear) { - clearOutputs(context); - } - else { - for (BuildTarget<?> target : projectDescriptor.getBuildTargetIndex().getAllTargets()) { - if (context.getScope().isAffected(target)) { - clearOutputFiles(context, target); - } + if (shouldClear) { + clearOutputs(context); + } + else { + for (BuildTarget<?> target : projectDescriptor.getBuildTargetIndex().getAllTargets()) { + if (context.getScope().isAffected(target)) { + clearOutputFilesUninterruptibly(context, target); } } } - catch (IOException e) { - throw new ProjectBuildException("Error cleaning output files", e); - } try { projectDescriptor.timestamps.getStorage().clean(); @@ -442,17 +436,13 @@ public class IncProjectBuilder { for (String srcPath : map.getSources()) { final Collection<String> outs = map.getOutputs(srcPath); if (outs != null && !outs.isEmpty()) { + List<String> deletedPaths = new ArrayList<String>(); for (String out : outs) { - final File outFile = new File(out); - final boolean deleted = outFile.delete(); - if (deleted && dirsToDelete != null) { - final File parent = outFile.getParentFile(); - if (parent != null) { - dirsToDelete.add(parent); - } - } + BuildOperations.deleteRecursively(out, deletedPaths, dirsToDelete); + } + if (!deletedPaths.isEmpty()) { + context.processMessage(new FileDeletedEvent(deletedPaths)); } - context.processMessage(new FileDeletedEvent(outs)); } } registerTargetsWithClearedOutput(context, Collections.singletonList(target)); @@ -479,7 +469,7 @@ public class IncProjectBuilder { } } - private void clearOutputs(CompileContext context) throws ProjectBuildException, IOException { + private void clearOutputs(CompileContext context) throws ProjectBuildException { final MultiMap<File, BuildTarget<?>> rootsToDelete = new MultiMapBasedOnSet<File, BuildTarget<?>>(); final Set<File> allSourceRoots = new HashSet<File>(); @@ -550,7 +540,7 @@ public class IncProjectBuilder { ); // clean only those files we are aware of for (BuildTarget<?> target : entry.getValue()) { - clearOutputFiles(context, target); + clearOutputFilesUninterruptibly(context, target); } } } @@ -561,6 +551,20 @@ public class IncProjectBuilder { ); } + private static void clearOutputFilesUninterruptibly(CompileContext context, BuildTarget<?> target) { + try { + clearOutputFiles(context, target); + } + catch (Throwable e) { + LOG.info(e); + String reason = e.getMessage(); + if (reason == null) { + reason = e.getClass().getName(); + } + context.processMessage(new CompilerMessage("", BuildMessage.Kind.WARNING, "Problems clearing output files for target \"" + target.getPresentableName() + "\": " + reason)); + } + } + private static void runTasks(CompileContext context, final List<BuildTask> tasks) throws ProjectBuildException { for (BuildTask task : tasks) { task.build(context); @@ -965,26 +969,20 @@ public class IncProjectBuilder { for (String deletedSource : pathsForIteration) { // deleting outputs corresponding to non-existing source final Collection<String> outputs = sourceToOutputStorage.getOutputs(deletedSource); - if (outputs != null && !outputs.isEmpty()) { - if (logger.isEnabled()) { - logger.logDeletedFiles(outputs); - } - + List<String> deletedOutputPaths = new ArrayList<String>(); for (String output : outputs) { - final File outFile = new File(output); - final boolean deleted = outFile.delete(); + final boolean deleted = BuildOperations.deleteRecursively(output, deletedOutputPaths, shouldPruneEmptyDirs ? dirsToDelete : null); if (deleted) { doneSomething = true; - if (shouldPruneEmptyDirs) { - final File parent = outFile.getParentFile(); - if (parent != null) { - dirsToDelete.add(parent); - } - } } } - context.processMessage(new FileDeletedEvent(outputs)); + if (!deletedOutputPaths.isEmpty()) { + if (logger.isEnabled()) { + logger.logDeletedFiles(deletedOutputPaths); + } + context.processMessage(new FileDeletedEvent(deletedOutputPaths)); + } } if (target instanceof ModuleBuildTarget) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 6aa91c246544..dcc97f4a9da5 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -60,8 +60,7 @@ import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.module.JpsModuleType; import org.jetbrains.jps.service.JpsServiceManager; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.*; import java.net.ServerSocket; import java.util.*; @@ -81,6 +80,7 @@ public class JavaBuilder extends ModuleLevelBuilder { public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null; private static final Key<Integer> JAVA_COMPILER_VERSION_KEY = Key.create("_java_compiler_version_"); public static final Key<Boolean> IS_ENABLED = Key.create("_java_compiler_enabled_"); + private static final Key<Boolean> IS_COMPILER_API_SUPPORTED = Key.create("_java_compiler_api_supported_"); private static final Key<AtomicReference<String>> COMPILER_VERSION_INFO = Key.create("_java_compiler_version_info_"); private static final Set<String> FILTERED_OPTIONS = new HashSet<String>(Arrays.<String>asList( @@ -138,7 +138,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } final boolean isJavac = JavaCompilers.JAVAC_ID.equalsIgnoreCase(compilerId) || JavaCompilers.JAVAC_API_ID.equalsIgnoreCase(compilerId); final boolean isEclipse = JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId) || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId); - IS_ENABLED.set(context, isJavac || isEclipse); + IS_COMPILER_API_SUPPORTED.set(context, isJavac || isEclipse); String messageText = null; if (isJavac) { messageText = "Using javac " + System.getProperty("java.version") + " to compile java sources"; @@ -158,7 +158,7 @@ public class JavaBuilder extends ModuleLevelBuilder { @NotNull ModuleChunk chunk, @NotNull DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder, @NotNull OutputConsumer outputConsumer) throws ProjectBuildException, IOException { - if (!IS_ENABLED.get(context, Boolean.TRUE)) { + if (!IS_ENABLED.get(context, Boolean.TRUE) || !IS_COMPILER_API_SUPPORTED.get(context, Boolean.TRUE)) { return ExitCode.NOTHING_DONE; } return doBuild(context, chunk, dirtyFilesHolder, outputConsumer); diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java index 556db38f3b54..2661e6a6a069 100644 --- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java +++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java @@ -163,7 +163,7 @@ public abstract class PlatformIdTableBuilding { highlighter = editorHighlighter; } else { - highlighter = HighlighterFactory.createHighlighter(null, myFile); + highlighter = HighlighterFactory.createHighlighter(inputData.getProject(), myFile); highlighter.setText(chars); } diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java index b9f8ec632b3c..dca89ac7bf8a 100644 --- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java +++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java @@ -28,6 +28,7 @@ import com.intellij.psi.search.IndexPatternProvider; import com.intellij.psi.tree.TokenSet; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.IntInlineKeyDescriptor; import com.intellij.util.io.KeyDescriptor; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NonNls; @@ -82,15 +83,10 @@ public class TodoIndex extends FileBasedIndexExtension<TodoIndexEntry, Integer> } }; - private final DataExternalizer<Integer> myValueExternalizer = new DataExternalizer<Integer>() { + private final DataExternalizer<Integer> myValueExternalizer = new IntInlineKeyDescriptor() { @Override - public void save(final DataOutput out, final Integer value) throws IOException { - out.writeInt(value.intValue()); - } - - @Override - public Integer read(final DataInput in) throws IOException { - return Integer.valueOf(in.readInt()); + protected boolean isCompactFormat() { + return true; } }; @@ -131,7 +127,7 @@ public class TodoIndex extends FileBasedIndexExtension<TodoIndexEntry, Integer> @Override public int getVersion() { - return 5; + return 6; } @Override diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java index d108c6030e6c..adc24b1a1c95 100644 --- a/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java +++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/IndexPatternSearcher.java @@ -29,6 +29,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.impl.cache.CacheUtil; import com.intellij.psi.impl.cache.TodoCacheManager; import com.intellij.psi.search.IndexPattern; import com.intellij.psi.search.IndexPatternOccurrence; @@ -187,15 +188,7 @@ public class IndexPatternSearcher implements QueryExecutor<IndexPatternOccurrenc if (lexer.getTokenStart() >= range.getEndOffset()) break; } - boolean isComment = commentTokens.contains(tokenType); - if (!isComment) { - final Language commentLang = tokenType.getLanguage(); - final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(commentLang); - if (parserDefinition != null) { - final TokenSet langCommentTokens = parserDefinition.getCommentTokens(); - isComment = langCommentTokens.contains(tokenType); - } - } + boolean isComment = commentTokens.contains(tokenType) || CacheUtil.isInComments(tokenType); if (isComment) { final int startDelta = builderForFile != null ? builderForFile.getCommentStartDelta(lexer.getTokenType()) : 0; diff --git a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java index 978a6c80c9e4..27f7d10b1646 100644 --- a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java +++ b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java @@ -37,6 +37,7 @@ public abstract class StubProcessingHelperBase { PsiFile _psifile = PsiManager.getInstance(project).findFile(file); PsiFileWithStubSupport psiFile = null; + boolean customStubs = false; if (_psifile != null && !(_psifile instanceof PsiPlainTextFile)) { _psifile = _psifile.getViewProvider().getStubBindingRoot(); @@ -44,7 +45,9 @@ public abstract class StubProcessingHelperBase { psiFile = (PsiFileWithStubSupport)_psifile; stubTree = psiFile.getStubTree(); if (stubTree == null && psiFile instanceof PsiFileImpl) { - stubTree = ((PsiFileImpl)psiFile).calcStubTree(); + BinaryFileStubBuilder stubBuilder = BinaryFileStubBuilders.INSTANCE.forFileType(psiFile.getFileType()); + if (stubBuilder == null) stubTree = ((PsiFileImpl)psiFile).calcStubTree(); + else customStubs = true; } } } @@ -57,6 +60,9 @@ public abstract class StubProcessingHelperBase { if (objectStubTree == null) { return true; } + if (customStubs && !(objectStubTree instanceof StubTree)) { + return processor.process((Psi)psiFile); // e.g. dom indices + } stubTree = (StubTree)objectStubTree; final List<StubElement<?>> plained = stubTree.getPlainList(); for (int i = 0, size = value.size(); i < size; i++) { diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java index bd324f7d7246..071330cc4d80 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java @@ -217,6 +217,7 @@ public class ManageCodeStyleSchemesDialog extends DialogWrapper { VirtualFile[] selection = fileChooser.choose(CodeStyleSchemesUIConfiguration.Util.getRecentImportFile(), null); if (selection.length == 1) { VirtualFile selectedFile = selection[0]; + selectedFile.refresh(false, false); CodeStyleSchemesUIConfiguration.Util.setRecentImportFile(selectedFile); try { InputStream nameInputStream = selectedFile.getInputStream(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java index c4379e2f223b..6017a40b4a9b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java @@ -129,7 +129,7 @@ public class BackspaceHandler extends EditorWriteActionHandler { editor.getDocument().deleteString(offset, offset + 1); } - else if (c == '"' || c == '\''){ + else if (c == '"' || c == '\'' || c == '`'){ char c1 = chars.charAt(offset); if (c1 != c) return true; if (wasClosingQuote) return true; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java index b6c0f77f1a9f..75ae804182d5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java @@ -213,8 +213,15 @@ public class CommentByLineCommentHandler implements CodeInsightActionHandler { int offset = myDocument.getLineStartOffset(myStartLine); offset = CharArrayUtil.shiftForward(myDocument.getCharsSequence(), offset, " \t"); - final Language languageSuitableForCompleteFragment = PsiUtilBase.reallyEvaluateLanguageInRange(offset, CharArrayUtil.shiftBackward( - myDocument.getCharsSequence(), myDocument.getLineEndOffset(myEndLine), " \t\n"), myFile); + int endOffset = CharArrayUtil.shiftBackward(myDocument.getCharsSequence(), myDocument.getLineEndOffset(myEndLine), " \t\n"); + final Language languageSuitableForCompleteFragment; + if (offset >= endOffset) { // we are on empty line + PsiElement element = myFile.findElementAt(offset); + if (element != null) languageSuitableForCompleteFragment = element.getParent().getLanguage(); + else languageSuitableForCompleteFragment = null; + } else { + languageSuitableForCompleteFragment = PsiUtilBase.reallyEvaluateLanguageInRange(offset, endOffset, myFile); + } Commenter blockSuitableCommenter = languageSuitableForCompleteFragment == null ? LanguageCommenters.INSTANCE.forLanguage(myFile.getLanguage()) : null; 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 55d8c3940017..818ab3cb2126 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java @@ -246,7 +246,7 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole public static AnAction createConsoleExecAction(final LanguageConsoleImpl languageConsole, final ProcessHandler processHandler, final ConsoleExecuteActionHandler consoleExecuteActionHandler) { - return new ConsoleExecuteAction(languageConsole, consoleExecuteActionHandler, ConsoleExecuteAction.CONSOLE_EXECUTE_ACTION_ID, + return new ConsoleExecuteAction(languageConsole, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(), new LanguageConsoleBuilder.ProcessBackedExecutionEnabledCondition(processHandler)); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index adbc722f6d10..376561535a1e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -62,7 +62,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring { ); private ResolveSnapshotProvider.ResolveSnapshot mySnapshot; private TextRange mySelectedRange; - private Language myLanguage; + protected Language myLanguage; public VariableInplaceRenamer(@NotNull PsiNamedElement elementToRename, Editor editor) { this(elementToRename, editor, elementToRename.getProject()); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 6f803ce35d66..cfadaeedc1dc 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1775,7 +1775,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { // important: no hard referencing currentFC to avoid OOME, the methods introduced for this purpose! final Computable<Boolean> update = index.update(inputId, currentFC); - final FileType fileType = file.getFileType(); scheduleUpdate(indexId, createUpdateComputableWithBufferingDisabled(update), @@ -1972,7 +1971,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { if (!fileIsDirectory && !isTooLarge(file)) { final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file); //noinspection ForLoopReplaceableByForEach - FileType fileType = file.getFileType(); boolean scheduleForUpdate = false; boolean resetStamp = false; @@ -2039,7 +2037,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { cleanProcessedFlag(file); IndexingStamp.flushCache(file); - final List<ID<?, ?>> affectedIndexCandidates = getAffectedIndexCandidates(file); + final List<ID<?, ?>> affectedIndexCandidates = IndexingStamp.getIndexedIds(file); final List<ID<?, ?>> affectedIndices = new ArrayList<ID<?, ?>>(affectedIndexCandidates.size()); //noinspection ForLoopReplaceableByForEach @@ -2047,14 +2045,10 @@ public class FileBasedIndexImpl extends FileBasedIndex { final ID<?, ?> indexId = affectedIndexCandidates.get(i); try { if (!needsFileContentLoading(indexId)) { - if (shouldUpdateIndex(file, indexId)) { - updateSingleIndex(indexId, file, null); - } + updateSingleIndex(indexId, file, null); } else { // the index requires file content - if (shouldUpdateIndex(file, indexId)) { - affectedIndices.add(indexId); - } + affectedIndices.add(indexId); } } catch (StorageException e) { @@ -2069,7 +2063,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { - FileType fileType = file.getFileType(); for (ID<?, ?> indexId : affectedIndices) { IndexingStamp.update(file, indexId, IndexInfrastructure.INVALID_STAMP2); } @@ -2408,11 +2401,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } - private boolean shouldUpdateIndex(final VirtualFile file, final ID<?, ?> indexId) { - return getInputFilter(indexId).acceptInput(file) && - (isMock(file) || isFileIndexed(file, indexId)); - } - private boolean shouldIndexFile(final VirtualFile file, final ID<?, ?> indexId) { return getInputFilter(indexId).acceptInput(file) && (isMock(file) || !isFileIndexed(file, indexId)); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java index 8531bcf688eb..35a304ef77e5 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java @@ -18,18 +18,21 @@ package com.intellij.util.indexing; import com.intellij.openapi.vfs.InvalidVirtualFileAccessException; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileWithId; import com.intellij.openapi.vfs.newvfs.FileAttribute; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; +import com.intellij.util.SmartList; import com.intellij.util.containers.ConcurrentHashMap; import com.intellij.util.io.DataInputOutputUtil; import gnu.trove.TObjectLongHashMap; import gnu.trove.TObjectLongProcedure; +import gnu.trove.TObjectProcedure; import org.jetbrains.annotations.Nullable; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.List; +import java.util.Collections; import java.util.concurrent.ArrayBlockingQueue; /** @@ -178,6 +181,28 @@ public class IndexingStamp { } } + public static List<ID<?,?>> getIndexedIds(final VirtualFile file) { + synchronized (getStripedLock(file)) { + try { + Timestamps stamp = createOrGetTimeStamp(file); + if (stamp != null && stamp.myIndexStamps != null && !stamp.myIndexStamps.isEmpty()) { + final SmartList<ID<?, ?>> retained = new SmartList<ID<?, ?>>(); + stamp.myIndexStamps.forEach(new TObjectProcedure<ID<?, ?>>() { + @Override + public boolean execute(ID<?, ?> object) { + retained.add(object); + return true; + } + }); + return retained; + } + } + catch (InvalidVirtualFileAccessException ignored /*ok to ignore it here*/) { + } + } + return Collections.emptyList(); + } + public static void flushCaches() { flushCache(null); myTimestampsCache.clear(); diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java index bfa99455c1a0..b18187610774 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java @@ -33,6 +33,7 @@ import java.util.*; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; public class InstalledPackagesPanel extends JPanel { protected final JButton myInstallButton; @@ -397,8 +398,11 @@ public class InstalledPackagesPanel extends JPanel { final Collection<InstalledPackage> finalPackages = packages; final Map<String, RepoPackage> cache = buildNameToPackageMap(packageManagementService.getAllPackagesCached()); + final boolean shouldFetchLatestVersionsForOnlyInstalledPackages = shouldFetchLatestVersionsForOnlyInstalledPackages(); if (cache.isEmpty()) { - refreshLatestVersions(); + if (!shouldFetchLatestVersionsForOnlyInstalledPackages) { + refreshLatestVersions(); + } } application.invokeLater(new Runnable() { @Override @@ -414,6 +418,9 @@ public class InstalledPackagesPanel extends JPanel { if (!cache.isEmpty()) { myPackagesTable.setPaintBusy(false); } + if (shouldFetchLatestVersionsForOnlyInstalledPackages) { + setLatestVersionsForInstalledPackages(); + } } } }, ModalityState.any()); @@ -423,6 +430,69 @@ public class InstalledPackagesPanel extends JPanel { }); } + private InstalledPackage getInstalledPackageAt(int index) { + return (InstalledPackage) myPackagesTableModel.getValueAt(index, 0); + } + + private void setLatestVersionsForInstalledPackages() { + final PackageManagementServiceEx serviceEx = getServiceEx(); + if (serviceEx == null) { + return; + } + final AtomicInteger restPackageCount = new AtomicInteger(0); + for (int i = 0; i < myPackagesTableModel.getRowCount(); ++i) { + final int finalIndex = i; + final InstalledPackage pkg = getInstalledPackageAt(finalIndex); + restPackageCount.incrementAndGet(); + serviceEx.fetchLatestVersion(pkg.getName(), new CatchingConsumer<String, Exception>() { + + private void decrement() { + if (restPackageCount.decrementAndGet() == 0) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + myPackagesTable.setPaintBusy(false); + } + }, ModalityState.any()); + } + } + + @Override + public void consume(Exception e) { + decrement(); + } + + @Override + public void consume(@Nullable final String latestVersion) { + if (latestVersion == null) { + decrement(); + return; + } + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (finalIndex < myPackagesTableModel.getRowCount()) { + InstalledPackage p = getInstalledPackageAt(finalIndex); + if (pkg == p) { + myPackagesTableModel.setValueAt(latestVersion, finalIndex, 2); + } + } + decrement(); + } + }, ModalityState.any()); + } + }); + } + } + + private boolean shouldFetchLatestVersionsForOnlyInstalledPackages() { + PackageManagementServiceEx serviceEx = getServiceEx(); + if (serviceEx != null) { + return serviceEx.shouldFetchLatestVersionsForOnlyInstalledPackages(); + } + return false; + } + private void refreshLatestVersions() { final Application application = ApplicationManager.getApplication(); application.executeOnPooledThread(new Runnable() { diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java index 8b53fe6b2747..7fb47ac0dbce 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java @@ -1,5 +1,6 @@ package com.intellij.webcore.packaging; +import com.intellij.util.CatchingConsumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -12,4 +13,8 @@ public abstract class PackageManagementServiceEx extends PackageManagementServic @Nullable String version, @NotNull Listener listener); + public abstract boolean shouldFetchLatestVersionsForOnlyInstalledPackages(); + + public abstract void fetchLatestVersion(@NotNull String packageName, @NotNull final CatchingConsumer<String, Exception> consumer); + } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/ssl/CertificatesManager.java b/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java index 9ade70c6fd84..1a6618664756 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/ssl/CertificatesManager.java +++ b/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java @@ -1,4 +1,4 @@ -package com.intellij.tasks.impl.ssl; +package com.intellij.util.net; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; @@ -7,20 +7,16 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.StreamUtil; -import org.apache.commons.httpclient.params.HttpConnectionParams; -import org.apache.commons.httpclient.protocol.Protocol; -import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import javax.net.ssl.*; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -62,43 +58,6 @@ public class CertificatesManager { } /** - * Creates instance of {@code Protocol} for registration by {@link org.apache.commons.httpclient.protocol.Protocol#registerProtocol(String, org.apache.commons.httpclient.protocol.Protocol)} - * <p/> - * See {@link #createSslContext()} for details - * - * @return protocol instance - */ - @Nullable - public Protocol createProtocol() { - try { - final SSLSocketFactory factory = createSslContext().getSocketFactory(); - return new Protocol("https", new ProtocolSocketFactory() { - @Override - public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) - throws IOException { - return factory.createSocket(host, port, localAddress, localPort); - } - - @Override - public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) - throws IOException { - return createSocket(host, port, localAddress, localPort); - } - - @Override - public Socket createSocket(String host, int port) throws IOException { - return factory.createSocket(host, port); - } - }, 443); - } - catch (Exception e) { - LOG.error(e); - return null; - } - } - - - /** * Creates special kind of {@code SSLContext} which X509TrustManager first checks certificate presence in * in default system-wide trust store (usually located at {@code ${JAVA_HOME}/lib/security/cacerts} or specified by * {@code javax.net.ssl.trustStore} property) and when in the one specified by first argument of factory method diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/ssl/UntrustedCertificateWarningDialog.form b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form index 2ba56f5023dc..c47867b508fe 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/ssl/UntrustedCertificateWarningDialog.form +++ b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.tasks.impl.ssl.UntrustedCertificateWarningDialog"> +<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.UntrustedCertificateWarningDialog"> <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="10" bottom="0" right="10"/> <constraints> diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/ssl/UntrustedCertificateWarningDialog.java b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java index eec105395bf8..b2a74ab44b9e 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/ssl/UntrustedCertificateWarningDialog.java +++ b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java @@ -1,4 +1,4 @@ -package com.intellij.tasks.impl.ssl; +package com.intellij.util.net; import com.intellij.icons.AllIcons; import com.intellij.openapi.diagnostic.Logger; diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java index 03e47c519a79..dfb004f3c150 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java @@ -330,7 +330,8 @@ public class EditorHyperlinkSupport { break; } } - int newIndex = i > 0 ? i % ranges.size() : 0; + int initial = i > 0 ? i % ranges.size() : 0; + int newIndex = initial; while (newIndex < ranges.size() && newIndex >= 0) { newIndex = (newIndex + delta + ranges.size()) % ranges.size(); final RangeHighlighter next = ranges.get(newIndex); @@ -342,7 +343,7 @@ public class EditorHyperlinkSupport { } }, newIndex == -1 ? -1 : newIndex + 1, ranges.size()); } - if (newIndex == i) { + if (newIndex == initial) { break; // cycled through everything, found no next/prev hyperlink } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index f9243cacec09..ddcfa870e4b5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -31,6 +31,7 @@ import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.*; import com.intellij.openapi.editor.impl.softwrap.*; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NotNull; @@ -340,7 +341,8 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume notifyListenersOnVisualLineStart(myContext.lineStartPosition); - if (!myContext.exceedsVisualEdge(newX)) { + if (!myContext.exceedsVisualEdge(newX) + || (myContext.currentPosition.offset == myContext.lineStartPosition.offset) && !Registry.is("editor.wrap.collapsed.region.at.line.start")) { myContext.advance(foldRegion, placeholderWidthInPixels); return true; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java index 16034e113809..092588caeb0a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java @@ -27,8 +27,12 @@ import com.intellij.openapi.vfs.VfsBundle; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.PathUtil; import com.intellij.util.io.UrlConnectionUtil; +import com.intellij.util.net.CertificatesManager; import org.jetbrains.annotations.NotNull; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; @@ -66,6 +70,21 @@ public class DefaultRemoteContentProvider extends RemoteContentProvider { HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection(); connection.setConnectTimeout(CONNECT_TIMEOUT); connection.setReadTimeout(READ_TIMEOUT); + if (connection instanceof HttpsURLConnection) { + try { + HttpsURLConnection httpsConnection = (HttpsURLConnection)connection; + httpsConnection.setHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + httpsConnection.setSSLSocketFactory(CertificatesManager.createDefault().createSslContext().getSocketFactory()); + } + catch (Exception e) { + LOG.warn(e); + } + } input = UrlConnectionUtil.getConnectionInputStreamWithException(connection, new EmptyProgressIndicator()); final int responseCode = connection.getResponseCode(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java index 96b5818f59f3..eaa1e63977c5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java @@ -480,7 +480,9 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider { } public void storeFullScreenStateIfNeeded() { - storeFullScreenStateIfNeeded(myFrameDecorator.isInFullScreen()); + if (myFrameDecorator != null) { + storeFullScreenStateIfNeeded(myFrameDecorator.isInFullScreen()); + } } public void storeFullScreenStateIfNeeded(boolean state) { diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java index 96bb850d0899..5565e77a8cfb 100644 --- a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java +++ b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java @@ -6,6 +6,8 @@ import io.netty.channel.group.DefaultChannelGroup; import io.netty.util.concurrent.ImmediateEventExecutor; import org.jetbrains.annotations.NotNull; +import java.util.concurrent.TimeUnit; + @ChannelHandler.Sharable public final class ChannelRegistrar extends ChannelInboundHandlerAdapter { private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); @@ -43,7 +45,7 @@ public final class ChannelRegistrar extends ChannelInboundHandlerAdapter { } try { - openChannels.close().awaitUninterruptibly(); + openChannels.close().awaitUninterruptibly(30, TimeUnit.SECONDS); } finally { if (eventLoopGroup != null) { diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index caaef0b5491b..fdc8e12b4bce 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -355,4 +355,5 @@ show.all.look.and.feels=false show.all.look.and.feels.description=Make accessible all available Look and Feels cvs.roots.refresh.uses.vfs=true cvs.roots.refresh.uses.vfs.description=Should CVS roots refresh after update use VFS +editor.wrap.collapsed.region.at.line.start=false diff --git a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java index 842ecfc5f160..6c0a9f10886b 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -18,7 +18,7 @@ package com.intellij.ide.bookmarks; import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest; +import com.intellij.openapi.editor.impl.AbstractEditorTest; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.vfs.VfsUtil; @@ -34,7 +34,7 @@ import java.util.List; * @author Denis Zhdanov * @since 12/27/10 1:43 PM */ -public class BookmarkManagerTest extends AbstractEditorProcessingOnDocumentModificationTest { +public class BookmarkManagerTest extends AbstractEditorTest { private final List<Bookmark> myBookmarks = new ArrayList<Bookmark>(); @Override diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java index c49532ca9315..be8801949905 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorProcessingOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -44,7 +44,7 @@ import java.util.regex.Pattern; * @author Denis Zhdanov * @since 11/18/10 7:43 PM */ -public abstract class AbstractEditorProcessingOnDocumentModificationTest extends LightPlatformCodeInsightTestCase { +public abstract class AbstractEditorTest extends LightPlatformCodeInsightTestCase { protected void init(@NotNull @NonNls String fileText, @NotNull TestFileType type) throws IOException { configureFromFileText(getFileName(type), fileText); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java new file mode 100644 index 000000000000..770d05621ad6 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapTest.java @@ -0,0 +1,102 @@ +/* + * 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.editor.impl.softwrap; + +import com.intellij.openapi.editor.FoldRegion; +import com.intellij.openapi.editor.SoftWrap; +import com.intellij.openapi.editor.impl.AbstractEditorTest; +import com.intellij.testFramework.EditorTestUtil; +import com.intellij.testFramework.TestFileType; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SoftWrapTest extends AbstractEditorTest { + + public void testCollapsedRegionWithLongPlaceholderAtLineStart1() throws IOException { + doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold>"); + } + + public void testCollapsedRegionWithLongPlaceholderAtLineStart2() throws IOException { + doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold><wrap>bar"); + } + + public void testCollapsedRegionWithLongPlaceholderAtLineStart3() throws IOException { + doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold>\nvery long <wrap>text"); + } + + private static final String TAGS_PATTERN = "(<fold(\\stext=\'([^\']*)\')?>)|(</fold>)|<wrap>"; + + private void doTestSoftWraps(int wrapWidth, String text) throws IOException { + List<MyFoldRegion> foldRegions = new ArrayList<MyFoldRegion>(); + List<Integer> wrapPositions = new ArrayList<Integer>(); + int foldInsertPosition = 0; + int pos = 0; + int docPos = 0; + Matcher matcher = Pattern.compile(TAGS_PATTERN).matcher(text); + StringBuilder cleanedText = new StringBuilder(); + while(matcher.find()) { + cleanedText.append(text.substring(pos, matcher.start())); + docPos += matcher.start() - pos; + pos = matcher.end(); + if (matcher.group(1) != null) { // <fold> + foldRegions.add(foldInsertPosition++, new MyFoldRegion(docPos, matcher.group(3), matcher.group(2) != null)); + } + else if (matcher.group(4) != null) { // </fold> + assertTrue("Misplaced closing fold marker tag: " + text, foldInsertPosition > 0); + foldRegions.get(--foldInsertPosition).endPos = docPos; + } + else { // <wrap> + wrapPositions.add(docPos); + } + } + assertTrue("Missing closing fold marker tag: " + text, foldInsertPosition == 0); + cleanedText.append(text.substring(pos)); + + init(cleanedText.toString(), TestFileType.TEXT); + + for (MyFoldRegion region : foldRegions) { + FoldRegion r = addFoldRegion(region.startPos, region.endPos, region.placeholder); + if (region.collapse) { + toggleFoldRegionState(r, false); + } + } + + EditorTestUtil.configureSoftWraps(myEditor, wrapWidth); + + List<Integer> actualWrapPositions = new ArrayList<Integer>(); + for (SoftWrap wrap : myEditor.getSoftWrapModel().getSoftWrapsForRange(0, myEditor.getDocument().getTextLength())) { + actualWrapPositions.add(wrap.getStart()); + } + assertEquals("Wrong wrap positions", wrapPositions, actualWrapPositions); + } + + private static class MyFoldRegion { + private final int startPos; + private int endPos; + private final String placeholder; + private final boolean collapse; + + private MyFoldRegion(int pos, String placeholder, boolean collapse) { + this.startPos = pos; + this.placeholder = placeholder; + this.collapse = collapse; + } + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java index bb15dbc655f2..c5e4b9555b6e 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java @@ -17,13 +17,13 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.codeInsight.folding.CodeFoldingManager; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest; -import com.intellij.openapi.editor.impl.DefaultEditorTextRepresentationHelper; +import com.intellij.openapi.editor.impl.AbstractEditorTest; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Ref; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.testFramework.EditorTestUtil; import com.intellij.testFramework.TestFileType; import gnu.trove.TIntHashSet; import gnu.trove.TIntProcedure; @@ -38,7 +38,7 @@ import java.util.List; * @author Denis Zhdanov * @since 09/16/2010 */ -public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorProcessingOnDocumentModificationTest { +public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorTest { private boolean mySmartHome; @@ -1055,28 +1055,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP private void init(final int visibleWidth, @NotNull String fileText, @NotNull TestFileType fileType, final int symbolWidth) throws IOException { init(fileText, fileType); - myEditor.getSettings().setUseSoftWraps(true); - SoftWrapModelImpl model = (SoftWrapModelImpl)myEditor.getSoftWrapModel(); - model.reinitSettings(); - - SoftWrapApplianceManager applianceManager = model.getApplianceManager(); - applianceManager.setWidthProvider(new SoftWrapApplianceManager.VisibleAreaWidthProvider() { - @Override - public int getVisibleAreaWidth() { - return visibleWidth; - } - }); - - if (symbolWidth > 0) { - applianceManager.setRepresentationHelper(new DefaultEditorTextRepresentationHelper(myEditor) { - @Override - public int charWidth(char c, int fontType) { - return symbolWidth; - } - }); - } - - applianceManager.registerSoftWrapIfNecessary(); + EditorTestUtil.configureSoftWraps(myEditor, visibleWidth, symbolWidth); } private static void checkSoftWraps(int... startOffsets) { diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java index 80998a056091..22ebe09a45b2 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java @@ -137,6 +137,7 @@ public class GeneralIdBasedToSMTRunnerEventsConvertor extends GeneralTestEventsP if (node != null) { if (node.getState() == State.REGISTERED && startedNodeEvent.isRunning()) { node.setState(State.RUNNING); + myRunningNodes.add(node); node.getProxy().setStarted(); if (suite) { fireOnSuiteStarted(node.getProxy()); @@ -172,13 +173,13 @@ public class GeneralIdBasedToSMTRunnerEventsConvertor extends GeneralTestEventsP State initialState = startedNodeEvent.isRunning() ? State.RUNNING : State.REGISTERED; node = new Node(startedNodeEvent.getId(), parentNode, childProxy, initialState); myNodeByIdMap.put(startedNodeEvent.getId(), node); - myRunningNodes.add(node); if (myLocator != null) { childProxy.setLocator(myLocator); } parentNode.getProxy().addChild(childProxy); if (node.getState() == State.RUNNING) { + myRunningNodes.add(node); // progress started childProxy.setStarted(); if (suite) { @@ -512,7 +513,7 @@ public class GeneralIdBasedToSMTRunnerEventsConvertor extends GeneralTestEventsP } } if (runningLeaves.isEmpty()) { - throw new RuntimeException("No running leaves found, running nodes: " + myRunningNodes); + return myTestsRootNode; } if (runningLeaves.size() == 1) { return runningLeaves.iterator().next(); diff --git a/platform/testFramework/src/com/intellij/testFramework/ActionTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ActionTestCase.java new file mode 100644 index 000000000000..7bc16e7db44b --- /dev/null +++ b/platform/testFramework/src/com/intellij/testFramework/ActionTestCase.java @@ -0,0 +1,100 @@ +/* + * 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.testFramework; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.CaretModel; +import com.intellij.openapi.editor.VisualPosition; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.fixtures.CodeInsightTestFixture; +import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; +import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; +import com.intellij.testFramework.fixtures.TestFixtureBuilder; +import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl; +import org.jetbrains.annotations.NotNull; + +/** + * User: Andrey.Vokin + * Date: 11/26/13 + */ +public abstract class ActionTestCase extends UsefulTestCase { + public static final String CARET_TAG_REPLACE_REGEX = EditorTestUtil.CARET_TAG_PREFIX + "(\\+\\d+)?>"; + protected CodeInsightTestFixture myFixture; + + protected abstract FileType getFileType(); + + protected abstract String getTestDataPath(); + + @Override + protected void setUp() throws Exception { + super.setUp(); + final IdeaTestFixtureFactory factory = IdeaTestFixtureFactory.getFixtureFactory(); + final TestFixtureBuilder<IdeaProjectTestFixture> fixtureBuilder = factory.createLightFixtureBuilder(null); + final IdeaProjectTestFixture fixture = fixtureBuilder.getFixture(); + myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(fixture, new LightTempDirTestFixtureImpl(true)); + myFixture.setUp(); + myFixture.setTestDataPath(getTestDataPath()); + } + + + @Override + protected void tearDown() throws Exception { + myFixture.tearDown(); + myFixture = null; + super.tearDown(); + } + + protected void doAction(@NotNull final String before, @NotNull String expected, @NotNull final Runnable action) { + int[] caretAndSelectionPositionInSourceFile = EditorTestUtil.getCaretAndSelectionPosition(before); + int[] caretAndSelectionPositionInExpectedFile = EditorTestUtil.getCaretAndSelectionPosition(expected); + + final String sourceFinal = before.replaceAll(CARET_TAG_REPLACE_REGEX, "").replace(EditorTestUtil.SELECTION_START_TAG, "").replace(EditorTestUtil.SELECTION_END_TAG, ""); + final String expectedFinal = expected.replaceAll(CARET_TAG_REPLACE_REGEX, "").replace(EditorTestUtil.SELECTION_START_TAG, "").replace(EditorTestUtil.SELECTION_END_TAG, ""); + + final PsiFile file = myFixture.configureByText(getFileType(), sourceFinal); + myFixture.getEditor().getSettings().setVirtualSpace(true); + if (caretAndSelectionPositionInSourceFile[0] >= 0) { + CaretModel caretModel = myFixture.getEditor().getCaretModel(); + caretModel.moveToOffset(caretAndSelectionPositionInSourceFile[0]); + if (caretAndSelectionPositionInSourceFile[1] != 0) { + int line = caretModel.getVisualPosition().getLine(); + int column = caretModel.getVisualPosition().getColumn(); + caretModel.moveToVisualPosition(new VisualPosition(line, column + caretAndSelectionPositionInSourceFile[1])); + } + } + + if (caretAndSelectionPositionInSourceFile[2] >= 0) { + myFixture.getEditor().getSelectionModel() + .setSelection(caretAndSelectionPositionInSourceFile[2], caretAndSelectionPositionInSourceFile[3]); + } + + ApplicationManager.getApplication().runWriteAction(action); + + if (caretAndSelectionPositionInExpectedFile[0] >= 0) { + assertEquals(caretAndSelectionPositionInExpectedFile[0], myFixture.getCaretOffset()); + if (caretAndSelectionPositionInExpectedFile[1] != 0) { + assertEquals(caretAndSelectionPositionInExpectedFile[1], myFixture.getEditor().getCaretModel().getVisualPosition().getColumn()); + } + } + if (caretAndSelectionPositionInExpectedFile[2] >= 0) { + assertEquals(caretAndSelectionPositionInExpectedFile[2], myFixture.getEditor().getSelectionModel().getSelectionStart()); + assertEquals(caretAndSelectionPositionInExpectedFile[3], myFixture.getEditor().getSelectionModel().getSelectionEnd()); + } + + assertEquals(expectedFinal, myFixture.getDocument(file).getText()); + } +} diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java index 5f7eb538fedb..2400ed5ee355 100644 --- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -23,6 +23,9 @@ import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.actionSystem.TypedAction; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.HighlighterIterator; +import com.intellij.openapi.editor.impl.DefaultEditorTextRepresentationHelper; +import com.intellij.openapi.editor.impl.SoftWrapModelImpl; +import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapApplianceManager; import com.intellij.psi.tree.IElementType; import junit.framework.Assert; import org.jetbrains.annotations.NotNull; @@ -132,4 +135,42 @@ public class EditorTestUtil { return new int[]{caretPosInSourceFile, visualColumnOffset, selectionStartInSourceFile, selectionEndInSourceFile}; } + + /** + * Configures given editor to wrap at given character count. + * + * @return whether any actual wraps of editor contents were created as a result of turning on soft wraps + */ + public static boolean configureSoftWraps(Editor editor, final int charCountToWrapAt) { + int charWidthInPixels = 7; + // we're adding 1 to charCountToWrapAt, to account for wrap character width, and 1 to overall width to overcome wrapping logic subtleties + return configureSoftWraps(editor, (charCountToWrapAt + 1) * charWidthInPixels + 1, charWidthInPixels); + } + + /** + * Configures given editor to wrap at given width, assuming characters are of given width + * + * @return whether any actual wraps of editor contents were created as a result of turning on soft wraps + */ + public static boolean configureSoftWraps(Editor editor, final int visibleWidth, final int charWidthInPixels) { + editor.getSettings().setUseSoftWraps(true); + SoftWrapModelImpl model = (SoftWrapModelImpl)editor.getSoftWrapModel(); + model.reinitSettings(); + + SoftWrapApplianceManager applianceManager = model.getApplianceManager(); + applianceManager.setWidthProvider(new SoftWrapApplianceManager.VisibleAreaWidthProvider() { + @Override + public int getVisibleAreaWidth() { + return visibleWidth; + } + }); + applianceManager.setRepresentationHelper(new DefaultEditorTextRepresentationHelper(editor) { + @Override + public int charWidth(char c, int fontType) { + return charWidthInPixels; + } + }); + applianceManager.registerSoftWrapIfNecessary(); + return !model.getRegisteredSoftWraps().isEmpty(); + } } diff --git a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java index 071dd4b3a22b..ed629b9ca353 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java @@ -34,7 +34,6 @@ import com.intellij.openapi.options.SchemesManagerFactory; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.impl.ProgressManagerImpl; import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -46,7 +45,6 @@ import com.intellij.psi.impl.PsiFileFactoryImpl; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl; import com.intellij.psi.util.CachedValuesManager; -import com.intellij.rt.execution.junit.FileComparisonFailure; import com.intellij.util.CachedValuesManagerImpl; import com.intellij.util.Function; import com.intellij.util.messages.MessageBus; @@ -57,7 +55,6 @@ import org.picocontainer.*; import org.picocontainer.defaults.AbstractComponentAdapter; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.Set; @@ -272,22 +269,8 @@ public abstract class ParsingTestCase extends PlatformLiteFixture { } public static void doCheckResult(String fullPath, String targetDataName, String text) throws IOException { - text = text.trim(); String expectedFileName = fullPath + File.separatorChar + targetDataName; - if (OVERWRITE_TESTDATA) { - VfsTestUtil.overwriteTestData(expectedFileName, text); - System.out.println("File " + expectedFileName + " created."); - } - try { - String expectedText = doLoadFile(fullPath, targetDataName); - if (!Comparing.equal(expectedText, text)) { - throw new FileComparisonFailure(targetDataName, expectedText, text, expectedFileName); - } - } - catch(FileNotFoundException e){ - VfsTestUtil.overwriteTestData(expectedFileName, text); - fail("No output text found. File " + expectedFileName + " created."); - } + UsefulTestCase.assertSameLinesWithFile(expectedFileName, text); } protected static String toParseTreeText(final PsiElement file, boolean skipSpaces, boolean printRanges) { diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 193fab53e851..5c262a0f0517 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -30,6 +30,7 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileVisitor; @@ -57,6 +58,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -687,10 +689,14 @@ public abstract class UsefulTestCase extends TestCase { String fileText; try { if (OVERWRITE_TESTDATA) { - FileUtil.writeToFile(new File(filePath), actualText); + VfsTestUtil.overwriteTestData(filePath, actualText); System.out.println("File " + filePath + " created."); } - fileText = FileUtil.loadFile(new File(filePath)); + fileText = FileUtil.loadFile(new File(filePath), CharsetToolkit.UTF8); + } + catch (FileNotFoundException e) { + VfsTestUtil.overwriteTestData(filePath, actualText); + throw new AssertionFailedError("No output text found. File " + filePath + " created."); } catch (IOException e) { throw new RuntimeException(e); diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java index 23c60fb3651d..e7c2e827cc06 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java @@ -194,9 +194,6 @@ public class GraphBuilder { // local package @NotNull public MutableGraph runBuild(@NotNull List<? extends GraphCommit> commitParentses) { - if (commitParentses.size() == 0) { - throw new IllegalArgumentException("Empty list commitParentses"); - } for (GraphCommit vcsCommit : commitParentses) { append(vcsCommit); } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java index a6fd7c1a93ea..4f052f5209fc 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java @@ -1,5 +1,6 @@ package com.intellij.vcs.log.graphmodel.impl; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.vcs.log.GraphCommit; @@ -30,6 +31,8 @@ public class GraphModelImpl implements GraphModel { private final List<Consumer<UpdateRequest>> listeners = new ArrayList<Consumer<UpdateRequest>>(); private final GraphBranchShowFixer branchShowFixer; + private static final Logger LOG = Logger.getInstance(GraphModelImpl.class); + private Function<Node, Boolean> isStartedBranchVisibilityNode = new Function<Node, Boolean>() { @NotNull @Override @@ -81,8 +84,15 @@ public class GraphModelImpl implements GraphModel { graph.updateVisibleRows(); int newSize = graph.getNodeRows().size(); - int newTo = newSize == 0 ? 0 : newSize - 1; - int oldTo = oldSize == 0 ? 0 : oldSize - 1; + if (newSize == 0) { // empty log. Possible only right after git init + return; + } + if (oldSize == 0) { // this shouldn't happen unless the log is empty + LOG.error("Old size can't be 0 if newSize is not 0. newSize: " + newSize); + return; + } + int newTo = newSize - 1; + int oldTo = oldSize - 1; UpdateRequest updateRequest = UpdateRequest.buildFromToInterval(0, oldTo, 0, newTo); callUpdateListener(updateRequest); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java index 266cb14e271a..1b75ba5f7102 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java @@ -776,7 +776,7 @@ public class VcsLogDataHolder implements Disposable { } public boolean isFullLogReady() { - return myFullLog; + return myFullLog && getTopCommitsCount() > 0; } @NotNull diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java index 940add3775ad..11f7540afd3e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogHashMap.java @@ -15,8 +15,12 @@ */ package com.intellij.vcs.log.data; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.util.io.IOUtil; import com.intellij.util.io.KeyDescriptor; import com.intellij.util.io.Page; import com.intellij.util.io.PersistentEnumerator; @@ -33,15 +37,21 @@ import java.io.IOException; /** * Supports the int <-> Hash persistent mapping. */ -class VcsLogHashMap { +class VcsLogHashMap implements Disposable { private static final File LOG_CACHE_APP_DIR = new File(PathManager.getSystemPath(), "vcs-log"); + private static final Logger LOG = Logger.getInstance(VcsLogHashMap.class); private final PersistentEnumerator<Hash> myPersistentEnumerator; VcsLogHashMap(@NotNull Project project) throws IOException { - File myMapFile = new File(LOG_CACHE_APP_DIR, project.getName() + "." + project.getLocationHash()); - myPersistentEnumerator = new PersistentEnumerator<Hash>(myMapFile, new MyHashKeyDescriptor(), Page.PAGE_SIZE); + final File myMapFile = new File(LOG_CACHE_APP_DIR, project.getName() + "." + project.getLocationHash()); + myPersistentEnumerator = IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentEnumerator<Hash>, IOException>() { + @Override + public PersistentEnumerator<Hash> compute() throws IOException { + return new PersistentEnumerator<Hash>(myMapFile, new MyHashKeyDescriptor(), Page.PAGE_SIZE); + } + }, myMapFile); } @Nullable @@ -53,6 +63,16 @@ class VcsLogHashMap { return myPersistentEnumerator.enumerate(hash); } + @Override + public void dispose() { + try { + myPersistentEnumerator.close(); + } + catch (IOException e) { + LOG.warn(e); + } + } + private static class MyHashKeyDescriptor implements KeyDescriptor<Hash> { @Override public void save(DataOutput out, Hash value) throws IOException { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java index c15af9fd5afc..fae4fa71d63b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java @@ -3,6 +3,7 @@ package com.intellij.vcs.log.ui; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLog; @@ -21,12 +22,14 @@ import com.intellij.vcs.log.impl.VcsLogImpl; import com.intellij.vcs.log.printmodel.SelectController; import com.intellij.vcs.log.ui.frame.MainFrame; import com.intellij.vcs.log.ui.frame.VcsLogGraphTable; +import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.table.TableModel; import java.awt.*; import java.util.Collection; +import java.util.Set; /** * @author erokhins @@ -82,8 +85,49 @@ public class VcsLogUI { }); } - public void setModel(@NotNull TableModel model) { - myMainFrame.getGraphTable().setModel(model); + public void setModel(@NotNull AbstractVcsLogTableModel model) { + VcsLogGraphTable table = getTable(); + int[] selectedRows = table.getSelectedRows(); + TableModel previousModel = table.getModel(); + + table.setModel(model); + + if (previousModel instanceof AbstractVcsLogTableModel) { // initially it is an empty DefaultTableModel + restoreSelection(table, (AbstractVcsLogTableModel)previousModel, selectedRows, model); + } + } + + private static void restoreSelection(@NotNull VcsLogGraphTable table, @NotNull AbstractVcsLogTableModel previousModel, + int[] previousSelectedRows, @NotNull AbstractVcsLogTableModel newModel) { + Set<Hash> selectedHashes = getHashesAtRows(previousModel, previousSelectedRows); + Set<Integer> rowsToSelect = findNewRowsToSelect(newModel, selectedHashes); + for (Integer row : rowsToSelect) { + table.addRowSelectionInterval(row, row); + } + } + + @NotNull + private static Set<Hash> getHashesAtRows(@NotNull AbstractVcsLogTableModel model, int[] rows) { + Set<Hash> hashes = ContainerUtil.newHashSet(); + for (int row : rows) { + Hash hash = model.getHashAtRow(row); + if (hash != null) { + hashes.add(hash); + } + } + return hashes; + } + + @NotNull + private static Set<Integer> findNewRowsToSelect(@NotNull AbstractVcsLogTableModel model, @NotNull Set<Hash> selectedHashes) { + Set<Integer> rowsToSelect = ContainerUtil.newHashSet(); + for (int row = 0; row < model.getRowCount() && rowsToSelect.size() < selectedHashes.size(); row++) {//stop iterating if found all hashes + Hash hash = model.getHashAtRow(row); + if (hash != null && selectedHashes.contains(hash)) { + rowsToSelect.add(row); + } + } + return rowsToSelect; } public void updateUI() { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index 44f58ddc67ae..f4401af18e4d 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -61,6 +61,10 @@ public class BranchesPanel extends JPanel { addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { + if (!myUI.getMainFrame().areGraphActionsEnabled()) { + return; + } + final RefGroup group = findRef(e); if (group == null) { return; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java index 248bfd932c5c..ef79df6275bd 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java @@ -188,8 +188,12 @@ class DetailsPanel extends JPanel implements ListSelectionListener { private final JTextField myBranchesList; ContainingBranchesPanel() { - JLabel label = new JBLabel("Contained in branches: "); - label.setFont(label.getFont().deriveFont(Font.ITALIC)); + JLabel label = new JBLabel("Contained in branches: ") { + @Override + public Font getFont() { + return UIUtil.getLabelFont().deriveFont(Font.ITALIC); + } + }; myLoadingIcon = new AsyncProcessIcon("Loading..."); myBranchesList = new JBTextField(""); myBranchesList.setEditable(false); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 8c6fd2f2486a..b41f98fb24f6 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -24,6 +24,7 @@ import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.ui.VcsLogUI; import com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi; import com.intellij.vcs.log.ui.filter.VcsLogFilterUi; +import com.intellij.vcs.log.ui.tables.GraphTableModel; import icons.VcsLogIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -151,14 +152,14 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { } private JComponent createActionsToolbar() { - AnAction hideBranchesAction = new DumbAwareAction("Collapse linear branches", "Collapse linear branches", VcsLogIcons.CollapseBranches) { + AnAction hideBranchesAction = new GraphAction("Collapse linear branches", "Collapse linear branches", VcsLogIcons.CollapseBranches) { @Override public void actionPerformed(AnActionEvent e) { myUI.hideAll(); } }; - AnAction showBranchesAction = new DumbAwareAction("Expand all branches", "Expand all branches", VcsLogIcons.ExpandBranches) { + AnAction showBranchesAction = new GraphAction("Expand all branches", "Expand all branches", VcsLogIcons.ExpandBranches) { @Override public void actionPerformed(AnActionEvent e) { myUI.showAll(); @@ -227,6 +228,10 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { return myToolbar; } + public boolean areGraphActionsEnabled() { + return myGraphTable.getModel() instanceof GraphTableModel && myGraphTable.getRowCount() > 0; + } + private class CommitSelectionListener implements ListSelectionListener { private final ChangesBrowser myChangesBrowser; @@ -290,5 +295,23 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { public void setSelected(AnActionEvent e, boolean state) { myUI.setLongEdgeVisibility(state); } + + @Override + public void update(AnActionEvent e) { + super.update(e); + e.getPresentation().setEnabled(areGraphActionsEnabled()); + } + } + + private abstract class GraphAction extends DumbAwareAction { + + public GraphAction(String text, String description, Icon icon) { + super(text, description, icon); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(areGraphActionsEnabled()); + } } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java index 0752ce3ebdbc..5b253d7d49e0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java @@ -51,16 +51,16 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender { @Override protected int getLeftPadding(JTable table, @Nullable Object value) { GraphCommitCell cell = (GraphCommitCell)value; - if (cell == null) { return 0; } + return calcPaddingBeforeText(cell, (Graphics2D)table.getGraphics()); + } - int refPadding = calcRefsPadding(cell.getRefsToThisCommit(), (Graphics2D)table.getGraphics()); - + private int calcPaddingBeforeText(GraphCommitCell cell, Graphics2D g) { + int refPadding = calcRefsPadding(cell.getRefsToThisCommit(), g); int countCells = cell.getPrintCell().countCell(); int graphPadding = countCells * WIDTH_NODE; - return refPadding + graphPadding; } @@ -82,9 +82,9 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender { return; } - BufferedImage image = UIUtil.createImage(1000, HEIGHT_CELL, BufferedImage.TYPE_INT_ARGB); + int width = calcPaddingBeforeText(cell, (Graphics2D)g); + BufferedImage image = UIUtil.createImage(width, HEIGHT_CELL, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); - g2.setBackground(new Color(0, 0, 0, 0)); graphPainter.draw(g2, cell.getPrintCell()); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java index 1e26910d938e..25c0397b9979 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java @@ -14,9 +14,9 @@ import javax.swing.table.AbstractTableModel; import java.util.List; /** - * @param <T> commit column class + * @param <CommitColumnClass> commit column class */ -public abstract class AbstractVcsLogTableModel<T> extends AbstractTableModel { +public abstract class AbstractVcsLogTableModel<CommitColumnClass> extends AbstractTableModel { public static final VirtualFile FAKE_ROOT = NullVirtualFile.INSTANCE; @@ -80,10 +80,10 @@ public abstract class AbstractVcsLogTableModel<T> extends AbstractTableModel { protected abstract VirtualFile getRoot(int rowIndex); @NotNull - protected abstract T getCommitColumnCell(int index, @Nullable VcsShortCommitDetails details); + protected abstract CommitColumnClass getCommitColumnCell(int index, @Nullable VcsShortCommitDetails details); @NotNull - protected abstract Class<T> getCommitColumnClass(); + protected abstract Class<CommitColumnClass> getCommitColumnClass(); /** * Returns the Hash of the commit displayed in the given row. diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java index c3d99b97bd70..e1e432d0368b 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java @@ -215,6 +215,17 @@ public class EclipseCodeStyleSchemeImporter implements SchemeImporter<CodeStyleS indentOptions.USE_TAB_CHARACTER = false; } } + else if (OPTION_CONTINUATION_INDENT.equals(key)) { + indentOptions.CONTINUATION_INDENT_SIZE = indentOptions.TAB_SIZE * valueToInt(value); + } + else if (OPTION_TAB_SIZE.equals(key)) { + int newTabSize = valueToInt(value); + int continuationTabs = indentOptions.TAB_SIZE > 0 ? indentOptions.CONTINUATION_INDENT_SIZE / indentOptions.TAB_SIZE : -1; + indentOptions.TAB_SIZE = newTabSize; + if (continuationTabs >= 0) { + indentOptions.CONTINUATION_INDENT_SIZE = continuationTabs * newTabSize; + } + } } } } diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties index 9c79740be0f5..b68e27948855 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties @@ -47,7 +47,7 @@ org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=Jav org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=Java:SPACE_BEFORE_WHILE_PARENTHESES org.eclipse.jdt.core.formatter.blank_lines_after_package=Java:BLANK_LINES_AFTER_PACKAGE #org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters= -org.eclipse.jdt.core.formatter.continuation_indentation=Java:IndentOptions:CONTINUATION_INDENT_SIZE +org.eclipse.jdt.core.formatter.continuation_indentation=Java:IndentOptions:<Programmatic> #org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator= org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=Java:ALIGN_MULTILINE_PARAMETERS_IN_CALLS #org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments= @@ -148,7 +148,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=Java: org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=Java:SPACE_BEFORE_COMMA #org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces= #org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression= -org.eclipse.jdt.core.formatter.tabulation.size=Java:IndentOptions:TAB_SIZE +org.eclipse.jdt.core.formatter.tabulation.size=Java:IndentOptions:<Programmatic> #org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference= org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE #org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block= diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java index b30a3a8af472..85158fef02a3 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java @@ -46,4 +46,6 @@ public interface EclipseXmlProfileElements { String OPTION_NEW_LINE_AT_EOF = "org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing"; String OPTION_INDENT_CLASS_BODY_DECL = "org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header"; String OPTION_TAB_CHAR = "org.eclipse.jdt.core.formatter.tabulation.char"; + String OPTION_CONTINUATION_INDENT = "org.eclipse.jdt.core.formatter.continuation_indentation"; + String OPTION_TAB_SIZE = "org.eclipse.jdt.core.formatter.tabulation.size"; } diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java index 200aed671c69..3fcbfa77a409 100644 --- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java +++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java @@ -31,6 +31,7 @@ public class EclipseSettingsImportTest extends PlatformTestCase { CommonCodeStyleSettings javaSettings = settings.getCommonSettings("Java"); CommonCodeStyleSettings.IndentOptions indentOptions = javaSettings.getIndentOptions(); + assertNotNull(indentOptions); javaSettings.SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS = false; javaSettings.SPACE_WITHIN_ARRAY_INITIALIZER_BRACES = false; javaSettings.ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE = true; @@ -93,6 +94,7 @@ public class EclipseSettingsImportTest extends PlatformTestCase { javaSettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE = true; indentOptions.USE_TAB_CHARACTER = false; indentOptions.SMART_TABS = false; + indentOptions.TAB_SIZE = 3; settings.FORMATTER_TAGS_ENABLED = false; InputStream inputStream = new FileInputStream(input); @@ -116,7 +118,7 @@ public class EclipseSettingsImportTest extends PlatformTestCase { assertFalse(javaSettings.CATCH_ON_NEW_LINE); assertTrue(javaSettings.SPACE_BEFORE_WHILE_PARENTHESES); assertEquals(1, javaSettings.BLANK_LINES_AFTER_PACKAGE); - assertEquals(2, javaSettings.getIndentOptions().CONTINUATION_INDENT_SIZE); + assertEquals(8, javaSettings.getIndentOptions().CONTINUATION_INDENT_SIZE); assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); assertEquals(0, javaSettings.BLANK_LINES_BEFORE_PACKAGE); assertFalse(javaSettings.SPACE_WITHIN_FOR_PARENTHESES); diff --git a/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java b/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java index 873b395e34ea..f70c9c670f85 100644 --- a/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java @@ -235,10 +235,10 @@ public class GitSimpleHandler extends GitTextHandler { }); runInCurrentThread(null); if (ex[0] != null) { - throw ex[0]; + throw new VcsException("Error executing " + printableCommandLine(), ex[0]); } if (result[0] == null) { - throw new VcsException("The git command returned null: " + myCommandLine.getCommandLineString()); + throw new VcsException("The git command returned null: " + printableCommandLine()); } return result[0]; } diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index 122892817675..0a76d10008fa 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -78,8 +78,12 @@ public class GitLogProvider implements VcsLogProvider { @Override public List<? extends VcsFullCommitDetails> readFirstBlock(@NotNull VirtualFile root, boolean ordered, int commitCount) throws VcsException { - String[] params = { "HEAD", "--branches", "--remotes", "--tags", "--encoding=UTF-8", "--full-history", "--sparse", - "--max-count=" + commitCount}; + if (!isRepositoryReady(root)) { + return Collections.emptyList(); + } + + String[] params = {"HEAD", "--branches", "--remotes", "--tags", "--encoding=UTF-8", "--full-history", "--sparse", + "--max-count=" + commitCount}; if (ordered) { params = ArrayUtil.append(params, "--date-order"); } @@ -89,6 +93,10 @@ public class GitLogProvider implements VcsLogProvider { @NotNull @Override public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException { + if (!isRepositoryReady(root)) { + return Collections.emptyList(); + } + return GitHistoryUtils.readAllHashes(myProject, root, userRegistry); } @@ -107,13 +115,11 @@ public class GitLogProvider implements VcsLogProvider { @NotNull @Override public Collection<VcsRef> readAllRefs(@NotNull VirtualFile root) throws VcsException { - myRepositoryManager.waitUntilInitialized(); - GitRepository repository = myRepositoryManager.getRepositoryForRoot(root); - if (repository == null) { - LOG.error("Repository not found for root " + root); + if (!isRepositoryReady(root)) { return Collections.emptyList(); } + GitRepository repository = getRepository(root); repository.update(); Collection<GitLocalBranch> localBranches = repository.getBranches().getLocalBranches(); Collection<GitRemoteBranch> remoteBranches = repository.getBranches().getRemoteBranches(); @@ -184,6 +190,10 @@ public class GitLogProvider implements VcsLogProvider { @Override public List<? extends VcsFullCommitDetails> getFilteredDetails(@NotNull final VirtualFile root, @NotNull Collection<VcsLogFilter> filters) throws VcsException { + if (!isRepositoryReady(root)) { + return Collections.emptyList(); + } + List<String> filterParameters = ContainerUtil.newArrayList(); List<VcsLogBranchFilter> branchFilters = ContainerUtil.findAll(filters, VcsLogBranchFilter.class); @@ -269,4 +279,24 @@ public class GitLogProvider implements VcsLogProvider { private static <T> String joinFilters(List<T> filters, Function<T, String> toString) { return StringUtil.join(filters, toString, "\\|"); } + + @Nullable + private GitRepository getRepository(@NotNull VirtualFile root) { + myRepositoryManager.waitUntilInitialized(); + return myRepositoryManager.getRepositoryForRoot(root); + } + + private boolean isRepositoryReady(@NotNull VirtualFile root) { + GitRepository repository = getRepository(root); + if (repository == null) { + LOG.error("Repository not found for root " + root); + return false; + } + else if (repository.isFresh()) { + LOG.info("Fresh repository: " + root); + return false; + } + return true; + } + }
\ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/documentation/GradleDocumentationProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/documentation/GradleDocumentationProvider.java index 4137a4f554dc..b9901b0825c6 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/documentation/GradleDocumentationProvider.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/documentation/GradleDocumentationProvider.java @@ -18,6 +18,7 @@ package org.jetbrains.plugins.gradle.documentation; import com.intellij.codeInsight.javadoc.JavaDocUtil; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -58,7 +59,7 @@ public class GradleDocumentationProvider implements DocumentationProvider { @Override public String generateDoc(PsiElement element, PsiElement originalElement) { PsiFile file = element.getContainingFile(); - if (file == null || !file.getName().endsWith(GradleConstants.EXTENSION)) return null; + if (file == null || !FileUtilRt.extensionEquals(file.getName(), GradleConstants.EXTENSION)) return null; return element instanceof GrLiteral ? findDoc(element, GrLiteral.class.cast(element).getValue()) : null; } @@ -66,7 +67,7 @@ public class GradleDocumentationProvider implements DocumentationProvider { @Override public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) { final PsiFile file = element.getContainingFile(); - if (file == null || !file.getName().endsWith(GradleConstants.EXTENSION)) return null; + if (file == null || !FileUtilRt.extensionEquals(file.getName(), GradleConstants.EXTENSION)) return null; final String doc = findDoc(element, object); return !StringUtil.isEmpty(doc) ? new CustomMembersGenerator.GdslNamedParameter(String.valueOf(object), doc, element, null) : null; } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java index 578398b67f55..e4ae7b389306 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java @@ -45,7 +45,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -204,9 +203,12 @@ public class GradleExecutionHelper { @NotNull GradleExecutionSettings settings, @NotNull ExternalSystemTaskNotificationListener listener) { - // use it only for customized wrapper - // TODO works correctly only or root project - if (settings.getDistributionType() != DistributionType.WRAPPED) return; + if (!settings.getDistributionType().isWrapped()) return; + + if (settings.getDistributionType() == DistributionType.DEFAULT_WRAPPED && + GradleUtil.findDefaultWrapperPropertiesFile(projectPath) != null) { + return; + } ProjectConnection connection = getConnection(projectPath, settings); try { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java index fe6f0c5cf433..2d201e5f3a3b 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java @@ -26,10 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.Serializable; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * @author Vladislav.Soroka @@ -114,14 +111,34 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM return null; } + /** + * Return collection path of modules provides the model + * @param modelClazz extra project model + * @return modules path collection + */ + @NotNull + public Collection<String> findModulesWithModel(@NotNull Class modelClazz) { + List<String> modules = new ArrayList<String>(); + for (Map.Entry<String, Object> set : projectsByPath.entrySet()) { + if (modelClazz.isInstance(set.getValue())) { + modules.add(extractModulePath(modelClazz, set.getKey())); + } + } + return modules; + } + public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @NotNull IdeaModule module) { projectsByPath.put(extractMapKey(modelClazz, module), project); } - @NotNull private static String extractMapKey(Class modelClazz, @NotNull IdeaModule module) { - return modelClazz.getName() + "@" + module.getGradleProject().getPath(); + return modelClazz.getName() + '@' + module.getGradleProject().getPath(); + } + + @NotNull + private static String extractModulePath(Class modelClazz, String key) { + return key.replaceFirst(modelClazz.getName() + '@', ""); } @Override diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java index f874946cd5c7..0f9bc3987e09 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java @@ -23,6 +23,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings; +import java.util.Collection; + /** * @author Vladislav.Soroka * @since 10/15/13 @@ -93,4 +95,9 @@ public class ProjectResolverContext { public <T> T getExtraProject(@NotNull IdeaModule module, Class<T> modelClazz) { return myModels.getExtraProject(module, modelClazz); } + + @NotNull + public Collection<String> findModulesWithModel(@NotNull Class modelClazz) { + return myModels.findModulesWithModel(modelClazz); + } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java index 03ac43cf75d9..213ba84271ef 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.gradle.service.project.wizard; import com.intellij.ide.util.newProjectWizard.AddModuleWizard; +import com.intellij.ide.util.projectWizard.ProjectBuilder; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.ide.wizard.Step; import com.intellij.openapi.externalSystem.service.project.wizard.SelectExternalProjectStep; @@ -70,15 +71,12 @@ public class GradleProjectOpenProcessor extends ProjectOpenProcessorBase<GradleP return step instanceof SelectExternalProjectStep; } }); - if (StringUtil.isEmpty(wizardContext.getProjectName())) { - final String projectName = dialog.getWizardContext().getProjectName(); - if (!StringUtil.isEmpty(projectName)) { - wizardContext.setProjectName(projectName); - } - } - dialog.show(); - return dialog.isOK(); + boolean result = dialog.showAndGet(); + if (result && getBuilder().getExternalProjectNode() != null) { + wizardContext.setProjectName(getBuilder().getExternalProjectNode().getData().getInternalName()); + } + return result; } @Override diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleClosureAsAnonymousParameterEnhancer.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleClosureAsAnonymousParameterEnhancer.java index 1cbec719f621..f6ef6c336677 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleClosureAsAnonymousParameterEnhancer.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleClosureAsAnonymousParameterEnhancer.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.gradle.service.resolve; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiType; import com.intellij.psi.PsiWildcardType; @@ -33,9 +34,7 @@ public class GradleClosureAsAnonymousParameterEnhancer extends ClosureAsAnonymou protected PsiType getClosureParameterType(GrClosableBlock closure, int index) { PsiFile file = closure.getContainingFile(); - if (file == null || !file.getName().endsWith(GradleConstants.EXTENSION)) { - return null; - } + if (file == null || !FileUtilRt.extensionEquals(file.getName(), GradleConstants.EXTENSION)) return null; PsiType psiType = super.getClosureParameterType(closure, index); if (psiType instanceof PsiWildcardType) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java index 84ab010aa46c..556d3b34efe6 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleImplicitContributor.java @@ -94,7 +94,7 @@ public class GradleImplicitContributor implements GradleMethodContextContributor checkForAvailableTasks(1, place.getText(), processor, state, place); } if (methodCallInfo.size() == 2) { - processAvailableTasks(methodCall, processor, state, place); + processAvailableTasks(methodCallInfo, methodCall, processor, state, place); } } @@ -192,7 +192,7 @@ public class GradleImplicitContributor implements GradleMethodContextContributor } } - private static void processAvailableTasks(@NotNull String taskName, + private static void processAvailableTasks(List<String> methodCallInfo, @NotNull String taskName, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @NotNull PsiElement place) { @@ -202,7 +202,8 @@ public class GradleImplicitContributor implements GradleMethodContextContributor if (canBeMethodOf(GroovyPropertyUtils.getGetterNameNonBoolean(taskName), gradleApiProjectClass)) return; final String className = BUILT_IN_TASKS.get(taskName); if (className != null) { - GradleResolverUtil.processDeclarations(psiManager, processor, state, place, className); + GradleResolverUtil.processDeclarations( + methodCallInfo.size() > 0 ? methodCallInfo.get(0) : null, psiManager, processor, state, place, className); } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java index 2cb97484470b..fc6bceacb429 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleScriptContributor.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.gradle.service.resolve; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.PsiTreeUtil; @@ -60,9 +61,8 @@ public class GradleScriptContributor extends NonCodeMembersContributor { } PsiFile file = aClass.getContainingFile(); - if (file == null || !file.getName().endsWith(GradleConstants.EXTENSION) || GradleConstants.SETTINGS_FILE_NAME.equals(file.getName())) { - return; - } + if (file == null || !FileUtilRt.extensionEquals(file.getName(), GradleConstants.EXTENSION) + || GradleConstants.SETTINGS_FILE_NAME.equals(file.getName())) return; List<String> methodInfo = ContainerUtilRt.newArrayList(); for (GrMethodCall current = PsiTreeUtil.getParentOfType(place, GrMethodCall.class); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java index c69e13230ae9..00d9ca5e193e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java @@ -72,9 +72,9 @@ public class GradleTaskManager extends AbstractExternalSystemTaskManager<GradleE @Nullable final String debuggerSetup, @NotNull final ExternalSystemTaskNotificationListener listener) throws ExternalSystemException { - if (settings != null) { - myHelper.ensureInstalledWrapper(id, projectPath, settings, listener); - } +// if (settings != null) { +// myHelper.ensureInstalledWrapper(id, projectPath, settings, listener); +// } // TODO add support for external process mode if (ExternalSystemApiUtil.isInProcessMode(GradleConstants.SYSTEM_ID)) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index a2704e2a8fbd..3bce9ce8ba34 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -369,3 +369,5 @@ annotation.attribute.expected=Annotation attribute expected highlight.constructor.calls.of.a.non.static.inner.classes.without.enclosing.instance.passed=Highlight constructor calls of non-static inner classes without enclosing instance passed doc.end.expected='*/' expected mixing.private.and.public.protected.methods.of.the.same.name=Mixing private and public/protected methods of the same name +explicit.constructors.are.not.allowed.in.immutable.class=Explicit constructors are not allowed for @Immutable class +repetitive.method.name.0=Repetitive method name ''{0}'' diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index e4dfc6d4a47a..136839183d14 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -91,6 +91,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureU import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.ast.GrInheritConstructorContributor; @@ -550,6 +551,9 @@ public class GroovyAnnotator extends GroovyElementVisitor { checkInnerMethod(myHolder, method); checkOptionalParametersInAbstractMethod(myHolder, method); + checkConstructorOfImmutableClass(myHolder, method); + checkGetterOfImmutable(myHolder, method); + final PsiElement nameIdentifier = method.getNameIdentifierGroovy(); if (nameIdentifier.getNode().getElementType() == GroovyTokenTypes.mSTRING_LITERAL) { checkStringLiteral(nameIdentifier); @@ -580,6 +584,43 @@ public class GroovyAnnotator extends GroovyElementVisitor { checkOverridingMethod(myHolder, method); } + private void checkGetterOfImmutable(AnnotationHolder holder, GrMethod method) { + if (!GroovyPropertyUtils.isSimplePropertyGetter(method)) return; + + PsiClass aClass = method.getContainingClass(); + if (aClass == null) return; + + PsiModifierList aClassModifierList = aClass.getModifierList(); + if (aClassModifierList == null) return; + + if (!PsiImplUtil.hasImmutableAnnotation(aClassModifierList)) return; + + + PsiField field = GroovyPropertyUtils.findFieldForAccessor(method, false); + if (field == null || !(field instanceof GrField)) return; + + GrModifierList fieldModifierList = ((GrField)field).getModifierList(); + if (fieldModifierList == null) return; + + if (fieldModifierList.hasExplicitVisibilityModifiers()) return; + + holder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("repetitive.method.name.0", method.getName())); + } + + private static void checkConstructorOfImmutableClass(AnnotationHolder holder, GrMethod method) { + if (!method.isConstructor()) return; + + PsiClass aClass = method.getContainingClass(); + if (aClass == null) return; + + PsiModifierList modifierList = aClass.getModifierList(); + if (modifierList == null) return; + + if (!PsiImplUtil.hasImmutableAnnotation(modifierList)) return; + + holder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("explicit.constructors.are.not.allowed.in.immutable.class")); + } + private static void checkOverridingMethod(@NotNull AnnotationHolder holder, @NotNull GrMethod method) { final List<HierarchicalMethodSignature> signatures = method.getHierarchicalMethodSignature().getSuperSignatures(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java index c86790d63a6c..2b2025d1e065 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/finalVar/GrFinalVariableAccessInspection.java @@ -43,6 +43,7 @@ import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.GrFieldControlFlowPolicy; +import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.*; @@ -310,6 +311,8 @@ public class GrFinalVariableAccessInspection extends BaseInspection { if (field instanceof GrEnumConstant) return true; if (field.getInitializerGroovy() != null) return true; + if (isImmutableField(field)) return true; + final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); final GrTypeDefinition aClass = ((GrTypeDefinition)field.getContainingClass()); @@ -367,6 +370,19 @@ public class GrFinalVariableAccessInspection extends BaseInspection { return true; } + private static boolean isImmutableField(@NotNull GrField field) { + GrModifierList fieldModifierList = field.getModifierList(); + if (fieldModifierList != null && fieldModifierList.hasExplicitVisibilityModifiers()) return false; + + PsiClass aClass = field.getContainingClass(); + if (aClass == null) return false; + + PsiModifierList modifierList = aClass.getModifierList(); + if (modifierList == null) return false; + + return PsiImplUtil.hasImmutableAnnotation(modifierList); + } + @NotNull private static List<GrMethod> getChainedConstructors(@NotNull GrMethod constructor) { final HashSet<Object> visited = ContainerUtil.newHashSet(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java index 4713c376eff2..90087a81c2aa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java @@ -60,6 +60,7 @@ import java.util.*; public abstract class GroovyShellActionBase extends DumbAwareAction { private static final Logger LOG = Logger.getInstance(GroovyShellActionBase.class); + public static final String GROOVY_SHELL_EXECUTE = "Groovy.Shell.Execute"; public static final Key<Boolean> GROOVY_SHELL_FILE = Key.create("GROOVY_SHELL_FILE"); private static final String GROOVY_SHELL_LAST_MODULE = "Groovy.Shell.LastModule"; @@ -166,7 +167,7 @@ public abstract class GroovyShellActionBase extends DumbAwareAction { final GroovyShellRunner shellRunner = getRunner(module); if (shellRunner == null) return; - AbstractConsoleRunnerWithHistory<LanguageConsoleView> runner = new GroovyConsoleRunner(getTitle(), shellRunner, module, "Groovy.Shell.Execute"); + AbstractConsoleRunnerWithHistory<LanguageConsoleView> runner = new GroovyConsoleRunner(getTitle(), shellRunner, module); try { runner.initAndRun(); } @@ -183,18 +184,15 @@ public abstract class GroovyShellActionBase extends DumbAwareAction { protected abstract LanguageConsoleImpl createConsole(Project project, String title); private class GroovyConsoleRunner extends AbstractConsoleRunnerWithHistory<LanguageConsoleView> { - private final String myEmptyExecuteAction; private GroovyShellRunner myShellRunner; private Module myModule; private GroovyConsoleRunner(@NotNull String consoleTitle, @NotNull GroovyShellRunner shellRunner, - @NotNull Module module, - @NotNull String emptyExecuteAction) { + @NotNull Module module) { super(module.getProject(), consoleTitle, shellRunner.getWorkingDirectory(module)); myShellRunner = shellRunner; myModule = module; - myEmptyExecuteAction = emptyExecuteAction; } @Override @@ -239,7 +237,7 @@ public abstract class GroovyShellActionBase extends DumbAwareAction { @Override public String getEmptyExecuteAction() { - return myEmptyExecuteAction; + return GROOVY_SHELL_EXECUTE; } }; new ConsoleHistoryController(getConsoleTitle(), null, getLanguageConsole(), handler.getConsoleHistoryModel()).install(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java index b35fb5a0f03b..8f9958b2a024 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java @@ -23,6 +23,7 @@ import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.FList; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; import groovy.lang.MetaMethod; @@ -53,7 +54,7 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.dsl.CustomMembersGenerator"); private static final GdslMembersProvider[] PROVIDERS = GdslMembersProvider.EP_NAME.getExtensions(); public static final String THROWS = "throws"; - private final List<Map> myDeclarations = ContainerUtil.newArrayList(); + private FList<Map> myDeclarations = FList.emptyList(); private final Project myProject; private final CompoundMembersHolder myDepot = new CompoundMembersHolder(); private final GroovyClassDescriptor myDescriptor; @@ -101,7 +102,8 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM addMemberHolder(new CustomMembersHolder() { @Override public boolean processMembers(GroovyClassDescriptor descriptor, PsiScopeProcessor processor, ResolveState state) { - return NonCodeMembersHolder.generateMembers(myDeclarations, descriptor.justGetPlaceFile()).processMembers(descriptor, processor, state); + return NonCodeMembersHolder.generateMembers(ContainerUtil.reverse(myDeclarations), descriptor.justGetPlaceFile()).processMembers( + descriptor, processor, state); } }); } @@ -166,9 +168,10 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM public void method(Map<Object, Object> args) { if (args == null) return; + args = ContainerUtil.newLinkedHashMap(args); parseMethod(args); args.put("declarationType", DeclarationType.METHOD); - myDeclarations.add(args); + myDeclarations = myDeclarations.prepend(args); } public void methodCall(Closure<Map<Object, Object>> generator) { @@ -253,23 +256,25 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM public void closureInMethod(Map<Object, Object> args) { if (args == null) return; + args = ContainerUtil.newLinkedHashMap(args); parseMethod(args); final Object method = args.get("method"); if (method instanceof Map) { parseMethod((Map)method); } args.put("declarationType", DeclarationType.CLOSURE); - myDeclarations.add(args); + myDeclarations = myDeclarations.prepend(args); } public void variable(Map<Object, Object> args) { if (args == null) return; + args = ContainerUtil.newLinkedHashMap(args); parseVariable(args); - myDeclarations.add(args); + myDeclarations = myDeclarations.prepend(args); } - private void parseVariable(Map<Object, Object> args) { + private static void parseVariable(Map<Object, Object> args) { String type = stringifyType(args.get("type")); args.put("type", type); args.put("declarationType", DeclarationType.VARIABLE); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java index 73d9621b769e..57c7d30930c5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java @@ -406,7 +406,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { ref.set(new ArrayList<Pair<File, GroovyDslExecutor>>()); //noinspection InstanceofCatchParameter if (e instanceof Error) { - stopGdsl = true; + stopGdsl(); } LOG.error(e); } @@ -419,7 +419,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { while (true) { ProgressManager.checkCanceled(); - if (stopGdsl) { + if (ourGdslStopped) { return Collections.emptyList(); } if (ref.get() != null || semaphore.waitFor(20)) { @@ -428,12 +428,16 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { } } + static void stopGdsl() { + ourGdslStopped = true; + } + private static final Key<CachedValue<List<GroovyDslScript>>> SCRIPTS_CACHE = Key.create("GdslScriptCache"); private static List<GroovyDslScript> getDslScripts(final Project project) { return CachedValuesManager.getManager(project).getCachedValue(project, SCRIPTS_CACHE, new CachedValueProvider<List<GroovyDslScript>>() { @Override public Result<List<GroovyDslScript>> compute() { - if (stopGdsl) { + if (ourGdslStopped) { return Result.create(Collections.<GroovyDslScript>emptyList(), Collections.emptyList()); } @@ -442,7 +446,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { List<GroovyDslScript> result = new ArrayList<GroovyDslScript>(); List<Pair<File, GroovyDslExecutor>> standardScripts = getStandardScripts(); - if (stopGdsl) { + if (ourGdslStopped) { return Result.create(Collections.<GroovyDslScript>emptyList(), Collections.emptyList()); } assert standardScripts != null; @@ -476,7 +480,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { } try { - while (count > 0 && !stopGdsl) { + while (count > 0 && !ourGdslStopped) { ProgressManager.checkCanceled(); final Pair<VirtualFile, GroovyDslExecutor> pair = queue.poll(20, TimeUnit.MILLISECONDS); if (pair != null) { @@ -562,11 +566,11 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { } } - private static volatile boolean stopGdsl = false; + private static volatile boolean ourGdslStopped = false; @Nullable private static GroovyDslExecutor createExecutor(String text, VirtualFile vfile, final Project project) { - if (stopGdsl) { + if (ourGdslStopped) { return null; } @@ -587,12 +591,12 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> { //noinspection InstanceofCatchParameter if (e instanceof OutOfMemoryError) { - stopGdsl = true; + stopGdsl(); throw (Error)e; } //noinspection InstanceofCatchParameter if (e instanceof NoClassDefFoundError) { - stopGdsl = true; + stopGdsl(); throw (NoClassDefFoundError) e; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java index 2ae6f07786b8..6508533b3574 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java @@ -27,7 +27,6 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiType; import com.intellij.psi.ResolveState; import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.MultiMap; import groovy.lang.Closure; @@ -77,7 +76,10 @@ public class GroovyDslScript { return holder.processMembers(descriptor, processor, state); } - catch (IncorrectOperationException e) { + catch (ProcessCanceledException e) { + throw e; + } + catch (Throwable e) { handleDslError(e); return true; } @@ -136,6 +138,9 @@ public class GroovyDslScript { } if (file != null) { GroovyDslFileIndex.invokeDslErrorPopup(e, project, file); + } else { + LOG.info("Error when executing internal GDSL " + myPath, e); + GroovyDslFileIndex.stopGdsl(); } return false; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java index 3525c44443b0..1fe5e6fa06e8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java @@ -95,6 +95,8 @@ import static com.intellij.psi.impl.source.tree.Factory.createSingleLeafElement; import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*; import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.RELATIONS; import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.SHIFT_SIGNS; +import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_IMMUTABLE; +import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_TRANSFORM_IMMUTABLE; public class PsiImplUtil { private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil"); @@ -842,4 +844,9 @@ public class PsiImplUtil { return null; } + + public static boolean hasImmutableAnnotation(PsiModifierList modifierList) { + return modifierList.findAnnotation(GROOVY_LANG_IMMUTABLE) != null || + modifierList.findAnnotation(GROOVY_TRANSFORM_IMMUTABLE) != null; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java index c482aea67a1b..1bd4bf957bba 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java @@ -49,8 +49,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEn import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.GrStubElementBase; +import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.stubs.GrModifierListStub; -import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import java.util.ArrayList; import java.util.Map; @@ -187,8 +187,7 @@ public class GrModifierListImpl extends GrStubElementBase<GrModifierListStub> im } if (pParent instanceof GrTypeDefinition) { PsiModifierList pModifierList = ((GrTypeDefinition)pParent).getModifierList(); - if (pModifierList != null && (pModifierList.findAnnotation(GroovyCommonClassNames.GROOVY_LANG_IMMUTABLE) != null || - pModifierList.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_IMMUTABLE) != null)) { + if (pModifierList != null && !modifierList.hasExplicitVisibilityModifiers() && PsiImplUtil.hasImmutableAnnotation(pModifierList)) { if (modifier.equals(GrModifier.FINAL)) return true; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralEscaper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralEscaper.java index 03f8b336afcc..19444200ee75 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralEscaper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralEscaper.java @@ -16,7 +16,6 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals; -import com.intellij.openapi.util.ProperTextRange; import com.intellij.openapi.util.TextRange; import com.intellij.psi.LiteralTextEscaper; import com.intellij.psi.tree.IElementType; @@ -34,7 +33,7 @@ public class GrLiteralEscaper extends LiteralTextEscaper<GrLiteralContainer> { @Override public boolean decode(@NotNull TextRange rangeInsideHost, @NotNull StringBuilder outChars) { - ProperTextRange.assertProperRange(rangeInsideHost); + TextRange.assertProperRange(rangeInsideHost); String subText = rangeInsideHost.substring(myHost.getText()); outSourceOffsets = new int[subText.length() + 1]; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrRegexImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrRegexImpl.java index 1d0be96e79d0..453b452f001d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrRegexImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrRegexImpl.java @@ -84,7 +84,7 @@ public class GrRegexImpl extends GrStringImpl implements GrRegex { @NotNull @Override public LiteralTextEscaper<? extends PsiLanguageInjectionHost> createLiteralTextEscaper() { - return null; + return new GrLiteralEscaper(this); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java index 537a4e486175..60673ed25c0b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -48,8 +49,7 @@ public class ConstructorAnnotationsProcessor extends AstTransformContributor { if (modifierList == null) return; final PsiAnnotation tupleConstructor = modifierList.findAnnotation(GROOVY_TRANSFORM_TUPLE_CONSTRUCTOR); - final boolean immutable = modifierList.findAnnotation(GROOVY_LANG_IMMUTABLE) != null || - modifierList.findAnnotation(GROOVY_TRANSFORM_IMMUTABLE) != null; + final boolean immutable = PsiImplUtil.hasImmutableAnnotation(modifierList); final boolean canonical = modifierList.findAnnotation(GROOVY_TRANSFORM_CANONICAL) != null; if (!immutable && !canonical && tupleConstructor == null) { return; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy index 60d3af345d6e..0b4271f0bbbb 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrFinalVariableAccessTest.groovy @@ -448,8 +448,9 @@ import groovy.transform.Immutable @Immutable class Money { - String <warning>currency</warning> - int <warning>amount</warning> + String currency + int amount + private final <warning>privateField</warning> void doubleYourMoney() { <error>amount</error> *= 2 diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy index edae8f8bb404..e5692615da6c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy @@ -1706,4 +1706,65 @@ class E { } ''') } + + void testImmutable() { + testHighlighting('''\ +import groovy.transform.Immutable + +@Immutable +class A { + String immutable + private String mutable + + def foo() { + <error descr="Cannot assign a value to final field 'immutable'">immutable</error> = 5 + mutable = 5 + + } +} +''') + } + + void testConstructorInImmutable() { + testHighlighting('''\ +import groovy.transform.Immutable + +@Immutable +class A { + String immutable + private String mutable + + def <error descr="Explicit constructors are not allowed for @Immutable class">A</error>() {} +} +''') + } + + void testGetterInImmutable() { + testHighlighting('''\ +import groovy.transform.Immutable + +@Immutable +class A { + String immutable + private String mutable + + String <error descr="Repetitive method name 'getImmutable'">getImmutable</error>() {immutable} + String getMutable() {mutable} +} +''') + } + + void testGetterInImmutable2() { + testHighlighting('''\ +import groovy.transform.Immutable + +@Immutable +class A { + String immutable + + int <error descr="Repetitive method name 'getImmutable'">getImmutable</error>() {1} +} +''') + } + }
\ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java index daf6ba94aac9..c5666e7481fb 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java @@ -39,6 +39,7 @@ public class HgCatCommand { final HgCommandExecutor executor = new HgCommandExecutor(myProject); executor.setOptions(Collections.<String>emptyList()); executor.setSilent(true); + executor.setOutputAlwaysSuppressed(true); executor.setCharset(charset); final HgCommandResult result = executor.executeInCurrentThread(hgFile.getRepo(), "cat", arguments); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java index d7697f792d65..42c30076e518 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java @@ -49,7 +49,7 @@ public abstract class HgChangesetsCommand { protected List<HgRevisionNumber> getRevisions(VirtualFile repo) { List<String> args = new ArrayList<String>(Arrays.asList( "--template", - HgChangesetUtil.makeTemplate("{rev}", "{node|short}", "{author}", "{desc|firstline}"), + HgChangesetUtil.makeTemplate("{rev}", "{node}", "{author}", "{desc|firstline}"), "--quiet" )); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java index 484aadcf9bd3..373dd12a7aad 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java @@ -272,7 +272,9 @@ public class HgLogCommand { if (myLogFile) { arguments.add(hgFile.getRelativePath()); } - return new HgCommandExecutor(myProject).executeInCurrentThread(repo, "log", arguments); + HgCommandExecutor commandExecutor = new HgCommandExecutor(myProject); + commandExecutor.setOutputAlwaysSuppressed(true); + return commandExecutor.executeInCurrentThread(repo, "log", arguments); } private static Set<String> parseFileList(String fileListString) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java index 80b0bc7ea918..a78ae5ec4aeb 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java @@ -184,7 +184,7 @@ public class HgWorkingCopyRevisionsCommand { boolean silent) { final List<String> args = new LinkedList<String>(); args.add("--template"); - args.add(HgChangesetUtil.makeTemplate("{rev}", "{node|short}")); + args.add(HgChangesetUtil.makeTemplate("{rev}", "{node}")); if (revision != null) { args.add("-r"); args.add(revision.getChangeset()); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java index a076635a228a..35a7077ef8b1 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java @@ -65,6 +65,8 @@ public final class HgCommandExecutor { @NotNull private Charset myCharset; private boolean myIsSilent = false; private boolean myShowOutput = false; + + private boolean myOutputAlwaysSuppressed = false; //for command with enormous output, like log or cat private List<String> myOptions = DEFAULT_OPTIONS; @Nullable private ModalityState myState; @@ -102,6 +104,10 @@ public final class HgCommandExecutor { myShowOutput = showOutput; } + public void setOutputAlwaysSuppressed(boolean outputAlwaysSuppressed) { + myOutputAlwaysSuppressed = outputAlwaysSuppressed; + } + public void execute(@Nullable final VirtualFile repo, @NotNull final String operation, @Nullable final List<String> arguments, @Nullable final HgCommandResultHandler handler) { HgUtil.executeOnPooledThreadIfNeeded(new Runnable() { @@ -206,7 +212,10 @@ public final class HgCommandExecutor { try { String workingDir = repo != null ? repo.getPath() : null; ShellCommand shellCommand = new ShellCommand(cmdLine, workingDir, myCharset); + long startTime = System.currentTimeMillis(); + LOG.debug(String.format("hg %s started", operation)); result = shellCommand.execute(); + LOG.debug(String.format("hg %s finished. Took %s ms", operation, System.currentTimeMillis() - startTime)); if (!HgErrorUtil.isAuthorizationError(result)) { passReceiver.saveCredentials(); } @@ -227,7 +236,6 @@ public final class HgCommandExecutor { } String warnings = warningReceiver.getWarnings(); result.setWarnings(warnings); - logResult(result); return result; } @@ -269,12 +277,14 @@ public final class HgCommandExecutor { if (unitTestMode) { System.out.print(result.getRawOutput() + "\n"); } - if (!myIsSilent && myShowOutput) { - LOG.info(result.getRawOutput()); - myVcs.showMessageInConsole(result.getRawOutput(), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes()); - } - else { - LOG.debug(result.getRawOutput()); + else if (!myOutputAlwaysSuppressed) { + if (!myIsSilent && myShowOutput) { + LOG.info(result.getRawOutput()); + myVcs.showMessageInConsole(result.getRawOutput(), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes()); + } + else { + LOG.debug(result.getRawOutput()); + } } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.java index 5aa5e8e2b956..cd00ccbb3414 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.java @@ -263,6 +263,10 @@ public class MavenArchetypesPanel implements Disposable { }); } + public boolean isSkipUpdateUI() { + return skipUpdateUI; + } + private void archetypeMayBeChanged() { MavenArchetype selectedArchetype = getSelectedArchetype(); if (((myBuilder.getArchetype() == null) != (selectedArchetype == null))) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java index cc33fae4c6a2..ef5d2451cab1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java @@ -199,6 +199,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { @Override public void updateStep() { + if (myArchetypes != null && myArchetypes.isSkipUpdateUI()) return; if (isMavenizedProject()) { MavenProject parent = myBuilder.findPotentialParentProject(myProjectOrNull); diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java index d0d7e4db8928..cf6d440d3755 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -20,8 +20,6 @@ import com.intellij.lang.properties.ResourceBundle; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; @@ -29,7 +27,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.intellij.util.SystemProperties; import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,13 +40,7 @@ import java.util.Properties; */ public class ResourceBundleUtil { - private static final String NATIVE_2_ASCII_CONVERSION_PATTERN = SystemProperties.getBooleanProperty("idea.native2ascii.lowercase", false) - ? "\\u%04x" : "\\u%04X"; - private static final TIntHashSet SYMBOLS_TO_ESCAPE = new TIntHashSet(new int[]{'#', '!', '=', ':'}); - private static final TIntHashSet UNICODE_SYMBOLS = new TIntHashSet(new int[]{ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'A', 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F' - }); private static final char ESCAPE_SYMBOL = '\\'; private ResourceBundleUtil() { @@ -125,15 +116,8 @@ public class ResourceBundleUtil { boolean escaped = false; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); - if (c == ESCAPE_SYMBOL && !escaped) { - char[] unicodeSymbols = parseUnicodeLiteral(text, i + 1); - if (unicodeSymbols != null) { - buffer.append(unicodeSymbols); - i += 5; - } - else { - escaped = true; - } + if (c == ESCAPE_SYMBOL && !escaped && (i == text.length() - 1 || (text.charAt(i + 1) != 'u' && text.charAt(i + 1) != 'U'))) { + escaped = true; continue; } if (escaped && c == 'n') { @@ -146,45 +130,6 @@ public class ResourceBundleUtil { } /** - * Tries to parse unicode literal contained at the given text at the given offset: - * <pre> - * "my string to process \uABCD - with unicode literal" - * ^ - * | - * offset - * </pre> - * I.e. this method checks if given text contains u[0123456789AaBbCcDdEeFf]{4} at the given offset; parses target unicode symbol - * and returns in case of the positive answer. - * - * @param text text to process - * @param i offset which might point to 'u' part of unicode literal contained at the given text - * @return 16-bit char symbols for the target unicode code point located at the given text at the given offset if any; - * <code>null</code> otherwise - */ - @Nullable - private static char[] parseUnicodeLiteral(@NotNull String text, int i) { - if (text.length() < i + 5) { - return null; - } - char c = text.charAt(i); - if (c != 'u' && c != 'U') { - return null; - } - for (int j = i + 1; j < i + 5; j++) { - if (!UNICODE_SYMBOLS.contains(text.charAt(j))) { - return null; - } - } - try { - int codePoint = Integer.parseInt(text.substring(i + 1, i + 5), 16); - return Character.toChars(codePoint); - } - catch (IllegalArgumentException e) { - return null; - } - } - - /** * Perform reverse operation to {@link #fromPropertyValueToValueEditor(String)}. * * @param text 'user-friendly' text shown to the user at the resource bundle editor @@ -205,17 +150,13 @@ public class ResourceBundleUtil { else if (c == ESCAPE_SYMBOL) { // Escaped 'escape' symbol) if (text.length() > i + 1) { final char nextChar = text.charAt(i + 1); - if (nextChar != 'n') { + if (nextChar != 'n' && nextChar != 'u' && nextChar != 'U') { buffer.append(ESCAPE_SYMBOL); } } else { buffer.append(ESCAPE_SYMBOL); } } - else if (c > 127) { // Non-ascii symbol - buffer.append(String.format(NATIVE_2_ASCII_CONVERSION_PATTERN, (int)c)); - continue; - } buffer.append(c); } return buffer.toString(); diff --git a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java index b7d8a7f60b0e..efd5b47d7626 100644 --- a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java +++ b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java @@ -35,6 +35,7 @@ import com.intellij.psi.xml.XmlTag; import com.intellij.util.IncorrectOperationException; import com.intellij.reference.SoftLazyValue; import com.intellij.util.containers.MultiMap; +import com.intellij.util.text.CharArrayUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -81,7 +82,14 @@ public class XmlPropertiesFile implements PropertiesFile { new CachedValueProvider<PropertiesFile>() { @Override public Result<PropertiesFile> compute() { - PropertiesFile value = !XmlPropertiesIndex.isAccepted(file.getText()) ? null : new XmlPropertiesFile(file); + CharSequence contents = file.getViewProvider().getContents(); + PropertiesFile value = null; + if (CharArrayUtil.indexOf(contents, XmlPropertiesIndex.HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD, 0) != -1 && + XmlPropertiesIndex.isAccepted(contents) + ) { + value = new XmlPropertiesFile(file); + } + return Result.create(value, file); } }, false); diff --git a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java index e29af4722802..467f656aeb71 100644 --- a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java +++ b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java @@ -31,6 +31,7 @@ public class XmlPropertiesIndex extends FileBasedIndexExtension<XmlPropertiesInd public static final ID<Key,String> NAME = ID.create("xmlProperties"); private static final EnumeratorStringDescriptor ENUMERATOR_STRING_DESCRIPTOR = new EnumeratorStringDescriptor(); + public static final String HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD = "http://java.sun.com/dtd/properties.dtd"; @NotNull @Override @@ -66,7 +67,7 @@ public class XmlPropertiesIndex extends FileBasedIndexExtension<XmlPropertiesInd @Override public int getVersion() { - return 1; + return 2; } @Override @@ -82,7 +83,11 @@ public class XmlPropertiesIndex extends FileBasedIndexExtension<XmlPropertiesInd @NotNull @Override public Map<Key, String> map(FileContent inputData) { - MyIXMLBuilderAdapter builder = parse(inputData.getContentAsText(), false); + CharSequence text = inputData.getContentAsText(); + if(CharArrayUtil.indexOf(text, HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD, 0) == -1) { + return Collections.emptyMap(); + } + MyIXMLBuilderAdapter builder = parse(text, false); if (builder == null) return Collections.emptyMap(); HashMap<Key, String> map = builder.myMap; if (builder.accepted) map.put(MARKER_KEY, ""); @@ -99,7 +104,7 @@ public class XmlPropertiesIndex extends FileBasedIndexExtension<XmlPropertiesInd StdXMLReader reader = new StdXMLReader(CharArrayUtil.readerFromCharSequence(text)) { @Override public Reader openStream(String publicID, String systemID) throws IOException { - if (!"http://java.sun.com/dtd/properties.dtd".equals(systemID)) throw new IOException(); + if (!HTTP_JAVA_SUN_COM_DTD_PROPERTIES_DTD.equals(systemID)) throw new IOException(); return new StringReader(" "); } }; diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/editor/ResourceBundleUtilTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/editor/ResourceBundleUtilTest.java index a3a514f2f287..158d3911b1b6 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/editor/ResourceBundleUtilTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/editor/ResourceBundleUtilTest.java @@ -1,3 +1,18 @@ +/* + * 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.lang.properties.editor; import gnu.trove.TIntHashSet; @@ -35,10 +50,11 @@ public class ResourceBundleUtilTest { { "\\ starting from white spaces", " starting from white spaces" }, { "\\ \t starting from white spaces and tabs", " \t starting from white spaces and tabs" }, { "first line \\\nsecond line", "first line \nsecond line" }, - - // Non-ascii symbols. - { "wei\\u00DF", "wei\u00DF" }, - + + // Non-ascii symbols and escaped characters + { "wei\u00DF", "wei\u00DF" }, + { "wei\\u00DF", "wei\\u00DF" }, + // All together. { "\\\t text with \\\nspecial symbols\\:\\\n\\#", "\t text with \nspecial symbols:\n#" } }; diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java index 0d6c2ecc09ec..65c2a2132aa8 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java @@ -3,7 +3,7 @@ package com.intellij.tasks.impl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.tasks.TaskRepositoryType; import com.intellij.tasks.config.TaskSettings; -import com.intellij.tasks.impl.ssl.CertificatesManager; +import com.intellij.util.net.CertificatesManager; import com.intellij.util.net.HttpConfigurable; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.auth.AuthScope; diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java index ab79c6703d2c..53ae66cd79f9 100644 --- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java +++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java @@ -167,7 +167,7 @@ public class FormsBindingManager extends FormsBuilder { FORMS_TO_COMPILE.set(context, srcToForms.isEmpty()? null : srcToForms); - if (config.isCopyFormsRuntimeToOutput() && !formsToCompile.isEmpty()) { + if (config.isCopyFormsRuntimeToOutput() && containsValidForm(formsToCompile.keySet())) { for (ModuleBuildTarget target : chunk.getTargets()) { if (!target.isTests()) { final File outputDir = target.getOutputDir(); @@ -189,6 +189,19 @@ public class FormsBindingManager extends FormsBuilder { return exitCode; } + private static boolean containsValidForm(Set<File> files) { + for (File file : files) { + try { + if (FormsParsing.readBoundClassName(file) != null) { + return true; + } + } + catch (IOException ignore) { + } + } + return false; + } + @NotNull private static Collection<File> findBoundSourceCandidates(CompileContext context, final ModuleBuildTarget target, File form) throws IOException { final List<JavaSourceRootDescriptor> targetRoots = context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context); diff --git a/plugins/ui-designer/jps-plugin/testData/build/alienFormFile/aa/NewJPanel.form b/plugins/ui-designer/jps-plugin/testData/build/alienFormFile/aa/NewJPanel.form new file mode 100644 index 000000000000..86321eac0dc7 --- /dev/null +++ b/plugins/ui-designer/jps-plugin/testData/build/alienFormFile/aa/NewJPanel.form @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="400" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="300" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + </Layout> +</Form> diff --git a/plugins/ui-designer/jps-plugin/testData/build/alienFormFile/aa/NewJPanel.java b/plugins/ui-designer/jps-plugin/testData/build/alienFormFile/aa/NewJPanel.java new file mode 100644 index 000000000000..ab612dcab63f --- /dev/null +++ b/plugins/ui-designer/jps-plugin/testData/build/alienFormFile/aa/NewJPanel.java @@ -0,0 +1,25 @@ +package aa; + +public class NewJPanel extends javax.swing.JPanel { + public NewJPanel() { + initComponents(); + } + + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 400, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + }// </editor-fold>//GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/ui-designer/jps-plugin/testSrc/org/jetbrains/jps/uiDesigner/build/FormsBuilderTest.java b/plugins/ui-designer/jps-plugin/testSrc/org/jetbrains/jps/uiDesigner/build/FormsBuilderTest.java index 2fbdaaf80d29..1bac0246be7e 100644 --- a/plugins/ui-designer/jps-plugin/testSrc/org/jetbrains/jps/uiDesigner/build/FormsBuilderTest.java +++ b/plugins/ui-designer/jps-plugin/testSrc/org/jetbrains/jps/uiDesigner/build/FormsBuilderTest.java @@ -17,6 +17,7 @@ package org.jetbrains.jps.uiDesigner.build; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.uiDesigner.core.AbstractLayout; import org.jetbrains.asm4.ClassReader; import org.jetbrains.asm4.ClassVisitor; import org.jetbrains.asm4.MethodVisitor; @@ -27,6 +28,7 @@ import org.jetbrains.jps.model.java.JpsJavaExtensionService; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.uiDesigner.compiler.FormsInstrumenter; import org.jetbrains.jps.uiDesigner.model.JpsUiDesignerExtensionService; +import org.jetbrains.jps.util.JpsPathUtil; import java.io.File; import java.io.IOException; @@ -40,6 +42,7 @@ public class FormsBuilderTest extends JpsBuildTestCase { public void testSimple() { JpsModule m = addModule("m", copyToProject(SIMPLE_FORM_PATH, "src")); makeAll().assertSuccessful(); + assertTrue(isRuntimeClassesCopied(m)); assertInstrumented(m, "xxx/MyForm.class"); makeAll().assertUpToDate(); } @@ -97,6 +100,17 @@ public class FormsBuilderTest extends JpsBuildTestCase { makeAll().assertUpToDate(); } + public void testDoNotCopyRuntimeClassesIfOnlyAlienFormFilesExist() { + JpsModule module = addModule("m", copyToProject("plugins/ui-designer/jps-plugin/testData/build/alienFormFile", "src")); + makeAll().assertSuccessful(); + assertFalse(isRuntimeClassesCopied(module)); + } + + private static boolean isRuntimeClassesCopied(JpsModule module) { + File outputDir = JpsPathUtil.urlToFile(JpsJavaExtensionService.getInstance().getOutputUrl(module, false)); + return new File(outputDir, AbstractLayout.class.getName().replace('.', '/') + ".class").exists(); + } + private static void assertNotInstrumented(JpsModule m, final String classPath) { assertFalse(isInstrumented(m, classPath)); } diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 7b1233fc92e2..0dbb11345883 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -484,6 +484,7 @@ tooltip tooltips toplink trebuchet +trie tuple twitter typedef diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java index a585f8834c25..c666f6e4ab2b 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java +++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java @@ -45,21 +45,20 @@ public class DomNamespaceKeyIndex extends StringStubIndexExtension<PsiFile> { if (!(file instanceof VirtualFileWithId)) return false; final int virtualFileId = ((VirtualFileWithId)file).getId(); - CommonProcessors.FindFirstProcessor<String> processor = - new CommonProcessors.FindFirstProcessor<String>() { + CommonProcessors.FindFirstProcessor<PsiFile> processor = new CommonProcessors.FindFirstProcessor<PsiFile>(); + StubIndex.getInstance().process( + KEY, + namespaceKey, + domFileElement.getFile().getProject(), + GlobalSearchScope.fileScope(domFileElement.getFile()), + new IdFilter() { @Override - protected boolean accept(String s) { - return namespaceKey.equals(s); + public boolean containsFileId(int id) { + return id == virtualFileId; } - }; - StubIndex.getInstance().processAllKeys(KEY, processor, - GlobalSearchScope.fileScope(domFileElement.getFile()), - new IdFilter() { - @Override - public boolean containsFileId(int id) { - return id == virtualFileId; - } - }); + }, + processor + ); return processor.isFound(); } diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java index d588d9c8d712..b7f6c81418da 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java @@ -196,7 +196,7 @@ public class XmlBlock extends AbstractXmlBlock { } - private List<Block> splitComment() { + protected List<Block> splitComment() { if (myNode.getElementType() != XmlElementType.XML_COMMENT) return EMPTY; final ArrayList<Block> result = new ArrayList<Block>(3); ASTNode child = myNode.getFirstChildNode(); |