diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index 390479e5847f..a6e4e0807f6b 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -366,11 +366,13 @@
-
+
+
+
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
index b98744badf14..c0e067a77652 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
@@ -1,91 +1,91 @@
-#
-# Copyright 2000-2007 JetBrains s.r.o.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-########################################################################################################################
-# Unuzed imports
-########################################################################################################################
-unused.import=Unused import
-optimize.imports=Optimize imports
-optimize.all.imports=Optimize unused import statements
-
-########################################################################################################################
-# Create class fix
-########################################################################################################################
-dialog.create.class.package.chooser.title=Choose destination package
-create.directory.command=Create directory
-destination.package=Destination package:
-dialog.create.class.label.0=Create class ''{0}''
-second.unsafe.call=Second unsafe call
-call.can.throw.npe=Calling chain can throw NullPointerException
-
-groovy.dfa.issues=Data flow issues
-
-unused.assignment=Unused Assignment
-unused.assignment.tooltip=Assignment is not used
-
-unused.inc.dec=Unused Incrementing or Decrementing
-
-unassigned.access=Variable Not Assigned
-unassigned.access.short.name=VariableNotAssigned
-unassigned.access.tooltip=Variable ''{0}'' might not be assigned
-no.return.display.name=Missing Return Statement
-no.return.short.name=MissingReturnStatement
-no.return.message=Not all execution paths return a value
-create.dynamic.property=Create dynamic property
-dynamic.property=Dynamic property
-unresolved.type.status=Type ''{0}'' is not resolved
-resolved.type.status=Type ''{0}'' is resolved
-no.type.specified=No type specified
-dynamic.element=Dynamic Element
-
-########################################################################################################################
-# InpectorGroovy properties
-########################################################################################################################
-pointless.boolean.problem.descriptor=#ref can be simplified to ''{0}'' #loc
-pointless.arithmetic.error.message=#ref can be replaced with ''{0}'' #loc
-pointless.boolean.display.name=Pointless boolean expression
-pointless.boolean.quickfix=Simplify
-
-Cannot.perform.undo.operation=Cannot perform undo operation
-Undo.disable=Undo Disabled
-field.already.defined=Variables with field names
-clashing.getters=Clashing getters
-
-access.to.inaccessible.element=Access to inaccessible element
-
-cannot.reference.nonstatic=Cannot reference nonstatic symbol ''{0}'' from static context
-
-type.doesnt.contain.method=Type ''{0}'' cannot be iterated in range because it does not have method ''{1}''
-incorrect.range.argument=Incorrect range arguments
-type.doesnt.implemnt.comparable=Type ''{0}'' doesnt implement Comparable
-add.method=Add method ''{0}()'' to class ''{1}''
-implement.class=Implement {0}
-fix.class=Fix class {0}
-check.labeled.statement=Labeled statement inspection
-unnecessary.qualified.reference=Unnecessary qualified reference
-rtype.cannot.contain.ltype=''{1}'' cannot contain ''{0}''
-new.instance.of.singleton=New instance of class annotated with @groovy.lang.Singleton
-replace.new.expression.with.0.instance=Replace with ''{0}.instance''
-getter.0.clashes.with.getter.1={0} clashes with {1}
-unused.0=Unused {0}
-remove.0=Remove {0}
-replace.postfix.0.with.prefix.0=Replace postfix {0} with prefix {0}
-replace.0.with.1=Replace {0} with binary {1}
-gr.deprecated.api.usage=Deprecated API inspection
-category,method.0.cannot.be.applied.to.1=Category method ''{0}'' cannot be applied to ''{1}''
-local.var.0.is.reassigned.in.closure=Local variable {0} is reassigned in {1} with other type
-anonymous.class=anonymous class
-closure=closure
-other.scope=Other scope
+#
+# Copyright 2000-2007 JetBrains s.r.o.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+########################################################################################################################
+# Unuzed imports
+########################################################################################################################
+unused.import=Unused import
+optimize.imports=Optimize imports
+optimize.all.imports=Optimize unused import statements
+
+########################################################################################################################
+# Create class fix
+########################################################################################################################
+dialog.create.class.package.chooser.title=Choose destination package
+create.directory.command=Create directory
+destination.package=Destination package:
+dialog.create.class.label.0=Create class ''{0}''
+second.unsafe.call=Second unsafe call
+call.can.throw.npe=Calling chain can throw NullPointerException
+
+groovy.dfa.issues=Data flow issues
+
+unused.assignment=Unused Assignment
+unused.assignment.tooltip=Assignment is not used
+
+unused.inc.dec=Unused Incrementing or Decrementing
+
+unassigned.access=Variable Not Assigned
+unassigned.access.short.name=VariableNotAssigned
+unassigned.access.tooltip=Variable ''{0}'' might not be assigned
+no.return.display.name=Missing Return Statement
+no.return.short.name=MissingReturnStatement
+no.return.message=Not all execution paths return a value
+create.dynamic.property=Create dynamic property
+dynamic.property=Dynamic property
+unresolved.type.status=Type ''{0}'' is not resolved
+resolved.type.status=Type ''{0}'' is resolved
+no.type.specified=No type specified
+dynamic.element=Dynamic Element
+
+########################################################################################################################
+# InpectorGroovy properties
+########################################################################################################################
+pointless.boolean.problem.descriptor=#ref can be simplified to ''{0}'' #loc
+pointless.arithmetic.error.message=#ref can be replaced with ''{0}'' #loc
+pointless.boolean.display.name=Pointless boolean expression
+pointless.boolean.quickfix=Simplify
+
+Cannot.perform.undo.operation=Cannot perform undo operation
+Undo.disable=Undo Disabled
+field.already.defined=Variables with field names
+clashing.getters=Clashing getters
+
+access.to.inaccessible.element=Access to inaccessible element
+
+cannot.reference.nonstatic=Cannot reference nonstatic symbol ''{0}'' from static context
+
+type.doesnt.contain.method=Type ''{0}'' cannot be iterated in range because it does not have method ''{1}''
+incorrect.range.argument=Incorrect range arguments
+type.doesnt.implemnt.comparable=Type ''{0}'' doesnt implement Comparable
+add.method=Add method ''{0}()'' to class ''{1}''
+implement.class=Implement {0}
+fix.class=Fix class {0}
+check.labeled.statement=Labeled statement inspection
+unnecessary.qualified.reference=Unnecessary qualified reference
+rtype.cannot.contain.ltype=''{1}'' cannot contain ''{0}''
+new.instance.of.singleton=New instance of class annotated with @groovy.lang.Singleton
+replace.new.expression.with.0.instance=Replace with ''{0}.instance''
+getter.0.clashes.with.getter.1={0} clashes with {1}
+unused.0=Unused {0}
+remove.0=Remove {0}
+replace.postfix.0.with.prefix.0=Replace postfix {0} with prefix {0}
+replace.0.with.1=Replace {0} with binary {1}
+gr.deprecated.api.usage=Deprecated API inspection
+category.method.0.cannot.be.applied.to.1=Category method ''{0}'' cannot be applied to ''{1}''
+local.var.0.is.reassigned.in.closure=Local variable {0} is reassigned in {1} with other type
+anonymous.class=anonymous class
+closure=closure
+other.scope=Other scope
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
index f8bf7e9ec443..d040d25406c5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
@@ -293,6 +293,8 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
private void checkConstructorCall(GrConstructorCall constructorCall, GroovyPsiElement refElement) {
final GrArgumentList argList = constructorCall.getArgumentList();
+ if (hasErrorElements(argList)) return;
+
if (!checkCannotInferArgumentTypes(refElement)) return;
final GroovyResolveResult constructorResolveResult = constructorCall.advancedResolve();
final PsiElement constructor = constructorResolveResult.getElement();
@@ -555,7 +557,21 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
}
}
+ /**
+ * checks only children of e
+ */
+ private static boolean hasErrorElements(@Nullable PsiElement e) {
+ if (e == null) return false;
+
+ for (PsiElement child = e.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child instanceof PsiErrorElement) return true;
+ }
+ return false;
+ }
+
private void checkMethodCall(GrMethodCall call) {
+ if (hasErrorElements(call.getArgumentList())) return;
+
final GrExpression expression = call.getInvokedExpression();
if (!(expression instanceof GrReferenceExpression)) { //it checks in visitRefExpr(...)
final PsiType type = expression.getType();
@@ -709,7 +725,7 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
final PsiType qualifier = inferQualifierTypeByPlace((GrReferenceExpression)place);
if (qualifier != null && !MixinMemberContributor.isCategoryMethod(staticMethod, qualifier, methodResolveResult.getSubstitutor())) {
registerError(((GrReferenceExpression)place).getReferenceNameElement(),
- GroovyInspectionBundle.message("category,method.0.cannot.be.applied.to.1", method.getName(),
+ GroovyInspectionBundle.message("category.method.0.cannot.be.applied.to.1", method.getName(),
qualifier.getCanonicalText()));
return false;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyFieldSemicolonSelectioner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyFieldSemicolonSelectioner.java
deleted file mode 100644
index 069415407696..000000000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyFieldSemicolonSelectioner.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.plugins.groovy.editor.selection;
-
-import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author Max Medvedev
- */
-public class GroovyFieldSemicolonSelectioner extends ExtendWordSelectionHandlerBase {
- @Override
- public boolean canSelect(PsiElement e) {
- return e instanceof GrVariableDeclaration;
- }
-
- @Override
- public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
- PsiElement next = e.getNextSibling();
- while (next != null &&
- next.getNode() != null &&
- TokenSets.WHITE_SPACES_SET.contains(next.getNode().getElementType()) &&
- !next.textContains('\n')) {
- next = next.getNextSibling();
- }
-
- final List ranges = new ArrayList();
- ranges.add(e.getTextRange());
- if (next != null && next.getNode().getElementType() == GroovyTokenTypes.mSEMI) {
- ranges.add(new TextRange(e.getTextRange().getStartOffset(), next.getTextRange().getEndOffset()));
- }
- return ranges;
- }
-}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyGStringSelectioner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyGStringSelectioner.java
index 2a1e1cf5a3f9..02793cb424c3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyGStringSelectioner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyGStringSelectioner.java
@@ -42,7 +42,7 @@ public class GroovyGStringSelectioner extends ExtendWordSelectionHandlerBase {
@Override
public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
- List ranges = new ArrayList();
+ List ranges = super.select(e, editorText, cursorOffset, editor);
PsiElement parent = e.getParent();
if (parent instanceof GrString) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyStatementSelectioner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyStatementSelectioner.java
new file mode 100644
index 000000000000..14c165ebe7f4
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyStatementSelectioner.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.editor.selection;
+
+import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandler;
+import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiWhiteSpace;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+import java.util.List;
+
+/**
+ * @author Max Medvedev
+ */
+public class GroovyStatementSelectioner implements ExtendWordSelectionHandler {
+ @Override
+ public boolean canSelect(PsiElement e) {
+ return e instanceof GrExpression && PsiUtil.isExpressionStatement(e) ||
+ (e instanceof GrStatement && !(e instanceof GrExpression)) ||
+ e.getNode().getElementType() == GroovyTokenTypes.mSEMI;
+ }
+
+ @Override
+ public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+ TextRange originalRange;
+
+ PsiElement first;
+ PsiElement last;
+ if (e instanceof GrStatement) {
+ first = e;
+ PsiElement next = e.getNextSibling();
+ next = skipWhitespacesForward(next);
+ if (next != null && next.getNode().getElementType() == GroovyTokenTypes.mSEMI) {
+ originalRange = new TextRange(e.getTextRange().getStartOffset(), next.getTextRange().getEndOffset());
+ last = next;
+ }
+ else {
+ originalRange = e.getTextRange();
+ last = e;
+ }
+ }
+
+ else {
+ last = e;
+ PsiElement prev = e.getPrevSibling();
+ prev = skipWhitespaceBack(prev);
+ if (prev instanceof GrStatement) {
+ originalRange = new TextRange(prev.getTextRange().getStartOffset(), e.getTextRange().getEndOffset());
+ first = prev;
+ }
+ else {
+ originalRange = e.getTextRange();
+ first = e;
+ }
+ }
+
+
+ final List ranges = ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, originalRange);
+
+
+ final TextRange blockRange = inferBlockRange(first, last);
+
+ if (!blockRange.equals(originalRange)) {
+ ranges.addAll(ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, blockRange, true));
+ }
+
+ return ranges;
+ }
+
+ private static TextRange inferBlockRange(PsiElement first, PsiElement last) {
+ while (true) {
+ PsiElement prev = first.getPrevSibling();
+
+ prev = skipWhitespaceBack(prev);
+ if (isOneLineFeed(prev)) prev = prev.getPrevSibling();
+ prev = skipWhitespaceBack(prev);
+ if (prev != null && prev.getNode().getElementType() == GroovyTokenTypes.mSEMI || prev instanceof GrStatement) {
+ first = prev;
+ }
+ else {
+ break;
+ }
+ }
+
+ while (true) {
+ PsiElement next = last.getNextSibling();
+
+ next = skipWhitespacesForward(next);
+ if (isOneLineFeed(next)) next = next.getNextSibling();
+ next = skipWhitespacesForward(next);
+ if (next != null && next.getNode().getElementType() == GroovyTokenTypes.mSEMI || next instanceof GrStatement) {
+ last = next;
+ }
+ else {
+ break;
+ }
+ }
+
+ return new TextRange(first.getTextRange().getStartOffset(), last.getTextRange().getEndOffset());
+ }
+
+ private static PsiElement skipWhitespacesForward(PsiElement next) {
+ while (isSpaceWithoutLineFeed(next)) next = next.getNextSibling();
+ return next;
+ }
+
+ private static PsiElement skipWhitespaceBack(PsiElement prev) {
+ while (isSpaceWithoutLineFeed(prev)) prev = prev.getPrevSibling();
+ return prev;
+ }
+
+ private static boolean isOneLineFeed(PsiElement e) {
+ if (e == null) return false;
+ if (!TokenSets.WHITE_SPACES_SET.contains(e.getNode().getElementType())) return false;
+
+ final String text = e.getText();
+ return text.indexOf('\n') == text.lastIndexOf('\n');
+ }
+
+ private static boolean isSpaceWithoutLineFeed(PsiElement e) {
+ return e instanceof PsiWhiteSpace && e.getText().indexOf('\n') == -1;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyWordSelectionFilter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyWordSelectionFilter.java
index 2f946f54f7a7..9dc7c35d5e5f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyWordSelectionFilter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyWordSelectionFilter.java
@@ -15,24 +15,18 @@
*/
package org.jetbrains.plugins.groovy.editor.selection;
-import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.IElementType;
-import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
-
-import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
+import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
/**
* @author Maxim.Medvedev
*/
public class GroovyWordSelectionFilter implements Condition {
public boolean value(PsiElement element) {
-
- final ASTNode node = element.getNode();
+return !(element instanceof GroovyPsiElement || element.getLanguage() == GroovyFileType.GROOVY_LANGUAGE);
+/* final ASTNode node = element.getNode();
if (node == null) return false;
final IElementType type = node.getElementType();
@@ -61,6 +55,6 @@ public class GroovyWordSelectionFilter implements Condition {
!(element instanceof GrArgumentList) &&
!(type == mDOLLAR)
- ;
+ ;*/
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyWordSelectionHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyWordSelectionHandler.java
new file mode 100644
index 000000000000..e19137ef12ea
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyWordSelectionHandler.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.editor.selection;
+
+import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandler;
+import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase;
+import com.intellij.codeInsight.editorActions.SelectWordUtil;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Max Medvedev
+ */
+public class GroovyWordSelectionHandler implements ExtendWordSelectionHandler {
+ private static final Logger LOG = Logger.getInstance(GroovyWordSelectionHandler.class);
+
+ @Override
+ public boolean canSelect(PsiElement e) {
+ return (e instanceof GroovyPsiElement || e.getLanguage() == GroovyFileType.GROOVY_LANGUAGE) &&
+ !(e.getNode().getElementType() == GroovyTokenTypes.mDOLLAR);
+ }
+
+ @Override
+ public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+ final TextRange originalRange = e.getTextRange();
+ LOG.assertTrue(originalRange.getEndOffset() <= editorText.length(), getClass() + "; " + e);
+
+ List ranges;
+ if (isSeparateStatement(e)) {
+ ranges = ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, originalRange, true);
+ if (ranges.size() == 1 && ranges.contains(originalRange)) {
+ ranges = ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, originalRange, false);
+ }
+ }
+ else {
+ ranges = new ArrayList();
+ ranges.add(e.getTextRange());
+ }
+
+ SelectWordUtil.addWordSelection(editor.getSettings().isCamelWords(), editorText, cursorOffset, ranges);
+
+ return ranges;
+ }
+
+ private static boolean isSeparateStatement(PsiElement e) {
+ return
+ e instanceof LeafPsiElement ||
+ e instanceof GrExpression && PsiUtil.isExpressionStatement(e) ||
+ e instanceof GrVariableDeclaration ||
+ e instanceof GrStatement && !(e instanceof GrExpression) ||
+ e instanceof GrMethod ||
+ e instanceof GrClassInitializer ||
+ e instanceof GrImportStatement ||
+ e instanceof GrPackageDefinition ||
+ e instanceof GrOpenBlock ||
+ e instanceof GrTypeDefinition && !((GrTypeDefinition)e).isAnonymous()
+ ;
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyActionsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyActionsTest.groovy
index 9aabfc97ea65..277c9324e357 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyActionsTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyActionsTest.groovy
@@ -57,7 +57,7 @@ public class GroovyActionsTest extends LightCodeInsightFixtureTestCase {
"a.foo(b)"
}
- public void testSWInCodeBlock() {doTestForSelectWord 3}
+ public void testSWInCodeBlock() {doTestForSelectWord 5}
public void testElseBranch() {
doTestForSelectWord (3, '''\
@@ -77,6 +77,46 @@ def foo() {
''')
}
+ void testBlocksOfCode() {
+ doTestForSelectWord(8, '''\
+this.allOptions = [:];
+ confTag.option.each{ opt ->
+ def value = opt.'@value';
+ if (value == null) {
+ value = opt.value ? opt.value[0].'@defaultName' : null;
+ }
+ this.allOptions[opt.'@name'] = value;
+ }
+
+ def moduleNode = confTag.module[0] ;
+ if (moduleNode != null && !"wholeProject".equals(this.allOptions['TEST_SEARCH_SCOPE'])) {
+ this.moduleRef = JpsElementFactory.instance.createModuleReference(moduleNode.'@name');
+ } else {
+ this.moduleRef = null;
+ }
+
+ this.macroExpander = macroExpander;
+''', '''\
+this.allOptions = [:];
+ confTag.option.each{ opt ->
+ def value = opt.'@value';
+ if (value == null) {
+ value = opt.value ? opt.value[0].'@defaultName' : null;
+ }
+ this.allOptions[opt.'@name'] = value;
+ }
+
+ def moduleNode = confTag.module[0] ;
+ if (moduleNode != null && !"wholeProject".equals(this.allOptions['TEST_SEARCH_SCOPE'])) {
+ this.moduleRef = JpsElementFactory.instance.createModuleReference(moduleNode.'@name');
+ } else {
+ this.moduleRef = null;
+ }
+
+ this.macroExpander = macroExpander;
+''')
+ }
+
private void doTestForSelectWord(int count, String input, String expected) {
myFixture.configureByText("a.groovy", input);
selectWord(count)