Merge remote-tracking branch 'origin/master'

This commit is contained in:
Sergey Rieder
2013-10-31 20:22:15 +04:00
65 changed files with 1411 additions and 730 deletions
-1
View File
@@ -3,7 +3,6 @@
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/jna-utils.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/jna.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/jna-platform.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -130,13 +130,8 @@ class ReloadClassesWorker {
continue;
}
redefineProcessor.processClass(qualifiedName, content);
if (myProgress.isCancelled()) {
break;
}
}
if (!myProgress.isCancelled()) {
redefineProcessor.processPending();
}
redefineProcessor.processPending();
myProgress.setFraction(1);
final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount();
@@ -288,9 +288,48 @@ public class HighlightUtil extends HighlightUtilBase {
}
@Nullable
static HighlightInfo checkIntersectionInTypeCast(@NotNull PsiTypeCastExpression expression) {
final PsiTypeElement castTypeElement = expression.getCastType();
if (castTypeElement == null) return null;
PsiType castType = castTypeElement.getType();
if (isIntersection(castTypeElement, castType)) {
if (PsiUtil.isLanguageLevel8OrHigher(expression)) {
final PsiTypeElement[] conjuncts = PsiTreeUtil.getChildrenOfType(castTypeElement, PsiTypeElement.class);
if (conjuncts != null) {
final List<PsiTypeElement> conjList = new ArrayList<PsiTypeElement>(Arrays.asList(conjuncts));
for (int i = 1; i < conjuncts.length; i++) {
final PsiTypeElement conjunct = conjuncts[i];
final PsiType conjType = conjunct.getType();
if (conjType instanceof PsiClassType) {
final PsiClass aClass = ((PsiClassType)conjType).resolve();
if (aClass != null && !aClass.isInterface()) {
final HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(conjunct)
.descriptionAndTooltip(JavaErrorMessages.message("interface.expected")).create();
QuickFixAction.registerQuickFixAction(errorResult, new FlipIntersectionSidesFix(aClass.getName(), conjList, conjunct, castTypeElement), null);
return errorResult;
}
}
}
}
} else {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(expression)
.descriptionAndTooltip("Intersection types in cast are not supported at this language level").create();
}
}
return null;
}
static boolean isIntersection(PsiTypeElement castTypeElement, PsiType castType) {
if (castType instanceof PsiIntersectionType) return true;
return PsiTreeUtil.getChildrenOfType(castTypeElement, PsiTypeElement.class) != null;
}
@Nullable
static HighlightInfo checkInconvertibleTypeCast(@NotNull PsiTypeCastExpression expression) {
PsiTypeElement castTypeElement = expression.getCastType();
final PsiTypeElement castTypeElement = expression.getCastType();
if (castTypeElement == null) return null;
PsiType castType = castTypeElement.getType();
@@ -306,6 +345,7 @@ public class HighlightUtil extends HighlightUtilBase {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create();
}
return null;
}
@@ -1336,6 +1336,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
super.visitTypeCastExpression(typeCast);
try {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIntersectionInTypeCast(typeCast));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast));
}
catch (IndexNotReadyException ignore) {
@@ -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.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* User: anna
* Date: 10/31/13
*/
public class FlipIntersectionSidesFix implements IntentionAction {
private static final Logger LOG = Logger.getInstance("#" + FlipIntersectionSidesFix.class.getName());
private final String myClassName;
private final List<PsiTypeElement> myConjuncts;
private final PsiTypeElement myConjunct;
private final PsiTypeElement myCastTypeElement;
public FlipIntersectionSidesFix(String className,
@NotNull List<PsiTypeElement> conjList,
PsiTypeElement conjunct,
PsiTypeElement castTypeElement) {
myClassName = className;
myConjuncts = conjList;
LOG.assertTrue(!conjList.isEmpty());
myConjunct = conjunct;
myCastTypeElement = castTypeElement;
}
@NotNull
@Override
public String getText() {
return "Move '" + myClassName + "' to the beginning";
}
@NotNull
@Override
public String getFamilyName() {
return "Move to front";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
for (PsiTypeElement typeElement : myConjuncts) {
if (!typeElement.isValid()) return false;
}
return !Comparing.strEqual(myConjunct.getText(), myConjuncts.get(0).getText());
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
myConjuncts.remove(myConjunct);
myConjuncts.add(0, myConjunct);
final String intersectionTypeText = StringUtil.join(myConjuncts, new Function<PsiTypeElement, String>() {
@Override
public String fun(PsiTypeElement element) {
return element.getText();
}
}, " & ");
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
final PsiTypeCastExpression fixedCast =
(PsiTypeCastExpression)elementFactory.createExpressionFromText("(" + intersectionTypeText + ") a", myCastTypeElement);
final PsiTypeElement fixedCastCastType = fixedCast.getCastType();
LOG.assertTrue(fixedCastCastType != null);
final PsiElement flippedTypeElement = myCastTypeElement.replace(fixedCastCastType);
CodeStyleManager.getInstance(project).reformat(flippedTypeElement);
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.daemon.impl.analysis;
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -26,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
/**
* User: anna
*/
class QualifyWithThisFix implements IntentionAction {
public class QualifyWithThisFix implements IntentionAction {
private final PsiClass myContainingClass;
private final PsiElement myExpression;
@@ -54,6 +55,7 @@ class QualifyWithThisFix implements IntentionAction {
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
final PsiThisExpression thisExpression =
RefactoringChangeUtil.createThisExpression(PsiManager.getInstance(project), myContainingClass);
((PsiReferenceExpression)myExpression).setQualifierExpression(thisExpression);
@@ -179,7 +179,15 @@ public class TypeConversionUtil {
}
return false;
}
else if (toType instanceof PsiIntersectionType) return false;
else if (toType instanceof PsiIntersectionType) {
if (fromType instanceof PsiClassType && ((PsiClassType)fromType).getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_8)) {
for (PsiType conjunct : ((PsiIntersectionType)toType).getConjuncts()) {
if (!isNarrowingReferenceConversionAllowed(fromType, conjunct)) return false;
}
return true;
}
return false;
}
if (fromType instanceof PsiDisjunctionType) {
return isNarrowingReferenceConversionAllowed(((PsiDisjunctionType)fromType).getLeastUpperBound(), toType);
@@ -445,14 +445,18 @@ public class InferenceSession {
}
else if (acceptObject || upperBounds.size() > 1 || !upperBounds.get(0).equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
PsiType glb = null;
for (PsiType upperBound : upperBounds) {
upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound, substitutor);
if (isProperType(upperBound, false)) {
if (glb == null) {
glb = upperBound;
}
else {
glb = GenericsUtil.getGreatestLowerBound(glb, upperBound);
if (isThrowable(upperBounds)) {
glb = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject()));
} else {
for (PsiType upperBound : upperBounds) {
upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound, substitutor);
if (isProperType(upperBound, false)) {
if (glb == null) {
glb = upperBound;
}
else {
glb = GenericsUtil.getGreatestLowerBound(glb, upperBound);
}
}
}
}
@@ -473,6 +477,20 @@ public class InferenceSession {
return substitutor;
}
private static boolean isThrowable(List<PsiType> upperBounds) {
boolean commonThrowable = false;
for (PsiType upperBound : upperBounds) {
if (upperBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) continue;
if (upperBound.equalsToText(CommonClassNames.JAVA_LANG_EXCEPTION) ||
upperBound.equalsToText(CommonClassNames.JAVA_LANG_THROWABLE)) {
commonThrowable = true;
} else {
return false;
}
}
return commonThrowable;
}
private PsiType acceptBoundsWithRecursiveDependencies(PsiTypeParameter typeParameter, PsiType bound, PsiSubstitutor substitutor) {
if (!isProperType(bound)) {
final PsiSubstitutor subst = PsiUtil.resolveClassInType(bound) != typeParameter ? substitutor.put(typeParameter, null) : substitutor;
@@ -0,0 +1,11 @@
import java.io.Serializable;
public class FooBar1 {
{
Object x = null;
Object y = (CharSequence & Serializable) x;
Object y2 = (CharSequence & Integer) x;
Object y3 = (Integer & CharSequence) x;
<error descr="Incompatible types. Found: 'java.lang.CharSequence & java.io.Serializable', required: 'int'">int y1 = (CharSequence & Serializable) x;</error>
}
}
@@ -0,0 +1,7 @@
// "Move 'Number' to the beginning" "true"
class C {
{
Object x = null;
Object y2 = (Number & CharSequence) x;
}
}
@@ -0,0 +1,7 @@
// "Move 'Number' to the beginning" "true"
class C {
{
Object x = null;
Object y2 = (CharSequence & Num<caret>ber) x;
}
}
@@ -0,0 +1,7 @@
// "Move 'Number' to the beginning" "false"
class C {
{
Object x = null;
Object y2 = (Number & Num<caret>ber) x;
}
}
@@ -13,24 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.refactoring.introduce.constant;
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.ui.components.JBCheckBox;
import javax.swing.*;
/**
* Created by Max Medvedev on 8/29/13
*/
public class GrInplaceIntroduceConstantPanel {
private JBCheckBox myMoveToAnotherClassJBCheckBox;
private JPanel myRootPane;
public boolean isMoveToAnotherClass() {
return myMoveToAnotherClassJBCheckBox.isSelected();
public class FlipIntersectionTypesTest extends LightQuickFixTestCase {
public void test() throws Exception {
doAllTests();
}
public JComponent getRootPane() {
return myRootPane;
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection";
}
}
Binary file not shown.
-1
View File
@@ -21,7 +21,6 @@ jgoodies-forms.jar
jgoodies-looks-2.4.2.jar
jh.jar
jna-utils.jar
jna-platform.jar
jna.jar
jsch-0.1.50.jar
jsr166e.jar
@@ -163,40 +163,39 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP
}
else {
final String decoded = decode(text);
if (decoded != null) {
if (context instanceof PackagePrefixFileSystemItem) {
context = ((PackagePrefixFileSystemItem)context).getDirectory();
if (context instanceof PackagePrefixFileSystemItem) {
context = ((PackagePrefixFileSystemItem)context).getDirectory();
}
if (context instanceof PsiDirectory && caseSensitivityApplies((PsiDirectory)context, caseSensitive)) {
// optimization: do not load all children into VFS
PsiDirectory directory = (PsiDirectory)context;
PsiFileSystemItem child = directory.findFile(decoded);
if (child == null) child = directory.findSubdirectory(decoded);
if (child != null) {
result.add(new PsiElementResolveResult(getOriginalFile(child)));
}
if (context instanceof PsiDirectory && caseSensitivityApplies((PsiDirectory)context, caseSensitive)) {
// optimization: do not load all children into VFS
PsiDirectory directory = (PsiDirectory)context;
PsiFileSystemItem child = directory.findFile(decoded);
if (child == null) child = directory.findSubdirectory(decoded);
if (child != null) {
result.add(new PsiElementResolveResult(getOriginalFile(child)));
}
else {
processVariants(context, new PsiFileSystemItemProcessor() {
@Override
public boolean acceptItem(String name, boolean isDirectory) {
return caseSensitive ? decoded.equals(name) : decoded.compareToIgnoreCase(name) == 0;
}
}
else {
processVariants(context, new PsiFileSystemItemProcessor() {
@Override
public boolean acceptItem(String name, boolean isDirectory) {
return caseSensitive ? decoded.equals(name) : decoded.compareToIgnoreCase(name) == 0;
}
@Override
public boolean execute(@NotNull PsiFileSystemItem element) {
result.add(new PsiElementResolveResult(getOriginalFile(element)));
return true;
}
});
}
@Override
public boolean execute(@NotNull PsiFileSystemItem element) {
result.add(new PsiElementResolveResult(getOriginalFile(element)));
return true;
}
});
}
}
}
}
@NotNull
public String getFileNameToCreate() {
return decode(getCanonicalText());
}
@@ -218,8 +217,8 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP
!myFileReferenceSet.isEndingSlashNotAllowed() && myIndex > 0);
}
@Nullable
public String decode(final String text) {
@NotNull
public String decode(@NotNull final String text) {
// strip http get parameters
String _text = text;
if (text.indexOf('?') >= 0) {
@@ -228,7 +227,7 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP
if (myFileReferenceSet.isUrlEncoded()) {
try {
return new URI(_text).getPath();
return StringUtil.notNullize(new URI(_text).getPath(), text);
}
catch (Exception e) {
return text;
@@ -504,7 +503,7 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP
public String getUnresolvedMessagePattern() {
return LangBundle.message("error.cannot.resolve")
+ " " + (isLast() ? LangBundle.message("terms.file") : LangBundle.message("terms.directory"))
+ " '" + StringUtil.escapePattern(StringUtil.notNullize(decode(getCanonicalText()))) + "'";
+ " '" + StringUtil.escapePattern(decode(getCanonicalText())) + "'";
}
public final boolean isLast() {
@@ -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.
@@ -44,7 +44,7 @@ import java.util.List;
// This prevents languages with polyadic expressions or sequences
// from reusing it, use simpleChooser instead.
public abstract class OccurrencesChooser<T> {
public static enum ReplaceChoice {
public enum ReplaceChoice {
NO("Replace this occurrence only"), NO_WRITE("Replace all occurrences but write"), ALL("Replace all {0} occurrences");
private final String myDescription;
@@ -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.
@@ -30,6 +30,7 @@ import com.intellij.lang.refactoring.NamesValidator;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.impl.FinishMarkAction;
@@ -327,7 +328,7 @@ public abstract class InplaceRefactoring {
new WriteCommandAction(myProject, getCommandName()) {
@Override
protected void run(com.intellij.openapi.application.Result result) throws Throwable {
protected void run(Result result) throws Throwable {
startTemplate(builder);
}
}.execute();
@@ -416,9 +416,7 @@ public class PathManager {
// helpers
private static String getAbsolutePath(String path) {
if (path.startsWith("~/") || path.startsWith("~\\")) {
path = getUserHome() + path.substring(1);
}
path = FileUtil.expandUserHome(path);
return new File(path).getAbsolutePath();
}
@@ -1213,6 +1213,13 @@ public class FileUtil extends FileUtilRt {
return path;
}
public static String expandUserHome(String path) {
if (path.startsWith("~/") || path.startsWith("~\\")) {
path = SystemProperties.getUserHome() + path.substring(1);
}
return path;
}
@NotNull
public static File[] notNullize(@Nullable File[] files) {
return notNullize(files, ArrayUtil.EMPTY_FILE_ARRAY);
@@ -0,0 +1,35 @@
/*
* 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.vcs.log;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
/**
* <p>This factory is used to create a particular {@link ContentRevision} instance which corresponds to the file and the commit hash.</p>
* <p>Different VCS plugins may use different {@link ContentRevision} implementation, therefore we need to be able
* to retrieve a correct instance for a commit.</p>
*/
public abstract class ContentRevisionFactory {
@NotNull
public abstract ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash);
@NotNull
public abstract ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash);
}
@@ -11,8 +11,8 @@ import java.util.List;
* <p>Full details of a commit: all metadata (commit message, author, committer, etc.) and the changes.</p>
* <p>These details will be shown in dedicated panels displayed near the log.</p>
* <p>An instance of this object can be obtained via
* {@link VcsLogObjectsFactory#createFullDetails(
* Hash, List, long, VirtualFile, String, String, String, String, String, String, long, List) VcsLogObjectsFactory#createFullDetails}</p>
* {@link VcsLogObjectsFactory#createFullDetails(Hash, List, long, VirtualFile, String, String, String, String, String, String, long,
* List, ContentRevisionFactory) VcsLogObjectsFactory#createFullDetails}</p>
*
* @author Kirill Likhodedov
*/
@@ -31,7 +31,8 @@ public interface VcsLogObjectsFactory {
@NotNull String subject,
@NotNull String authorName, @NotNull String authorEmail, @NotNull String message,
@NotNull String committerName,
@NotNull String committerEmail, long commitTime, @NotNull List<Change> changes);
@NotNull String committerEmail, long commitTime, @NotNull List<Change> changes,
@NotNull ContentRevisionFactory contentRevisionFactory);
@NotNull
VcsUser createUser(@NotNull String name);
@@ -1,11 +1,16 @@
package com.intellij.vcs.log.data;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.SimpleContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.ContentRevisionFactory;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.impl.VcsFullCommitDetailsImpl;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.Collections;
/**
@@ -19,7 +24,20 @@ public class LoadingDetails extends VcsFullCommitDetailsImpl {
private final long myLoadingTaskIndex;
public LoadingDetails(@NotNull Hash hash, long loadingTaskIndex, @NotNull VirtualFile root) {
super(hash, Collections.<Hash>emptyList(), -1, root, "Loading...", "", "", "", "", "", -1, Collections.<Change>emptyList());
super(hash, Collections.<Hash>emptyList(), -1, root, "Loading...", "", "", "", "", "", -1, Collections.<Change>emptyList(),
new ContentRevisionFactory() {
@NotNull
@Override
public ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash) {
return new SimpleContentRevision("", new FilePathImpl(file), hash.asString());
}
@NotNull
@Override
public ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash) {
return new SimpleContentRevision("", new FilePathImpl(new File(path), false), hash.asString());
}
});
myLoadingTaskIndex = loadingTaskIndex;
}
@@ -1,7 +1,12 @@
package com.intellij.vcs.log.impl;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.ContentRevisionFactory;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsFullCommitDetails;
import org.jetbrains.annotations.NotNull;
@@ -21,19 +26,24 @@ public class VcsFullCommitDetailsImpl extends VcsShortCommitDetailsImpl implemen
@NotNull private final String myCommitterEmail;
private final long myCommitTime;
@NotNull private final Collection<Change> myChanges;
@NotNull private final Collection<LightChange> myChanges;
public VcsFullCommitDetailsImpl(@NotNull Hash hash, @NotNull List<Hash> parents, long authorTime, @NotNull VirtualFile root,
@NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, @NotNull String message,
@NotNull String committerName, @NotNull String committerEmail, long commitTime,
@NotNull List<Change> changes) {
@NotNull List<Change> changes, @NotNull final ContentRevisionFactory contentRevisionFactory) {
super(hash, parents, authorTime, root, subject, authorName);
myAuthorEmail = authorEmail;
myCommitterName = committerName;
myCommitterEmail = committerEmail;
myCommitTime = commitTime;
myFullMessage = message;
myChanges = changes;
myChanges = ContainerUtil.map(changes, new Function<Change, LightChange>() {
@Override
public LightChange fun(Change change) {
return LightChange.create(contentRevisionFactory, VcsFullCommitDetailsImpl.this, change);
}
});
}
@Override
@@ -45,7 +55,12 @@ public class VcsFullCommitDetailsImpl extends VcsShortCommitDetailsImpl implemen
@Override
@NotNull
public final Collection<Change> getChanges() {
return myChanges;
return ContainerUtil.map(myChanges, new Function<LightChange, Change>() {
@Override
public Change fun(LightChange change) {
return change.toChange();
}
});
}
@Override
@@ -70,4 +85,79 @@ public class VcsFullCommitDetailsImpl extends VcsShortCommitDetailsImpl implemen
public long getCommitTime() {
return myCommitTime;
}
private static class LightChange {
private ContentRevisionFactory myContentRevisionFactory;
private VcsFullCommitDetails myDetails;
private boolean myModification;
private VirtualFile myBeforeFile;
private VirtualFile myAfterFile;
private String myBeforePath;
private String myAfterPath;
private static LightChange create(ContentRevisionFactory contentRevisionFactory, VcsFullCommitDetails details, Change change) {
LightChange lc = new LightChange();
Change.Type type = change.getType();
lc.myModification = type == Change.Type.MODIFICATION;
lc.myContentRevisionFactory = contentRevisionFactory;
ContentRevision before = change.getBeforeRevision();
if (before != null && !lc.myModification) { // don't store the same path twice (for modification store only after path)
FilePath filePath = before.getFile();
if (filePath.getVirtualFile() == null) {
lc.myBeforePath = filePath.getIOFile().getPath();
}
else {
lc.myBeforeFile = filePath.getVirtualFile();
}
}
ContentRevision after = change.getAfterRevision();
if (after != null) {
FilePath filePath = after.getFile();
if (filePath.getVirtualFile() == null) {
lc.myAfterPath = filePath.getIOFile().getPath();
}
else {
lc.myAfterFile = filePath.getVirtualFile();
}
}
lc.myDetails = details;
return lc;
}
Change toChange() {
List<Hash> parents = myDetails.getParents();
Hash parentHash = parents.isEmpty() ? null : parents.get(0); // no parents for the initial commit
ContentRevision before = null;
if (parentHash != null) {
if (myBeforeFile != null) {
before = myContentRevisionFactory.createRevision(myBeforeFile, parentHash);
}
else if (myBeforePath != null) {
before = myContentRevisionFactory.createRevision(myDetails.getRoot(), myBeforePath, parentHash);
}
}
ContentRevision after = null;
if (myAfterFile != null) {
after = myContentRevisionFactory.createRevision(myAfterFile, myDetails.getHash());
if (myModification && parentHash != null) { // we didn't store myBeforeFile/Path to avoid duplicate path
before = myContentRevisionFactory.createRevision(myAfterFile, parentHash);
}
}
else if (myAfterPath != null) {
after = myContentRevisionFactory.createRevision(myDetails.getRoot(), myAfterPath, myDetails.getHash());
if (myModification && parentHash != null) {
before = myContentRevisionFactory.createRevision(myDetails.getRoot(), myAfterPath, parentHash);
}
}
return new Change(before, after);
}
}
}
@@ -42,9 +42,10 @@ public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory {
public VcsFullCommitDetails createFullDetails(@NotNull Hash hash, @NotNull List<Hash> parents, long authorTime, @NotNull VirtualFile root,
@NotNull String subject, @NotNull String authorName, @NotNull String authorEmail,
@NotNull String message, @NotNull String committerName,
@NotNull String committerEmail, long commitTime, @NotNull List<Change> changes) {
@NotNull String committerEmail, long commitTime, @NotNull List<Change> changes,
@NotNull ContentRevisionFactory contentRevisionFactory) {
return new VcsFullCommitDetailsImpl(hash, parents, authorTime, root, subject, authorName, authorEmail, message, committerName,
committerEmail, commitTime, changes);
committerEmail, commitTime, changes, contentRevisionFactory);
}
@NotNull
@@ -518,6 +518,11 @@ public class ParenthesesUtils {
}
}
}
else if (parentExpression instanceof PsiConditionalExpression && expression instanceof PsiConditionalExpression) {
final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)parentExpression;
final PsiExpression condition = conditionalExpression.getCondition();
return PsiTreeUtil.isAncestor(condition, expression, true);
}
return parentPrecedence < childPrecedence;
}
}
@@ -11,4 +11,17 @@ class UnnecessaryParentheses {
}
return true;
}
}
class ConditionalCondition {
String s;
String t;
public boolean equals(Object other) {
if (!(other instanceof ConditionalCondition)) return false;
final ConditionalCondition condition = (ConditionalCondition)other;
return (s != null ? !s.equals(condition.s) : condition.s != null) ? false : t.equals(condition.t);
}
}
@@ -18,7 +18,6 @@ package com.siyeh.ipp.trivialif;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
@@ -36,8 +35,7 @@ public class ReplaceIfWithConditionalIntention extends Intention {
}
@Override
public void processIntention(@NotNull PsiElement element)
throws IncorrectOperationException {
public void processIntention(@NotNull PsiElement element) {
final PsiIfStatement ifStatement = (PsiIfStatement)element.getParent();
if (ifStatement == null) {
return;
@@ -183,9 +181,8 @@ public class ReplaceIfWithConditionalIntention extends Intention {
return null;
}
@NonNls final StringBuilder conditional = new StringBuilder();
final String conditionText = getExpressionText(condition);
conditional.append(conditionText);
conditional.append('?');
final String conditionText = getExpressionText(condition, true);
conditional.append(conditionText).append('?');
final PsiType thenType = thenValue.getType();
final PsiType elseType = elseValue.getType();
if (thenType instanceof PsiPrimitiveType &&
@@ -195,28 +192,24 @@ public class ReplaceIfWithConditionalIntention extends Intention {
// prevent unboxing of boxed value to preserve semantics (IDEADEV-36008)
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)thenType;
conditional.append(primitiveType.getBoxedTypeName());
conditional.append(".valueOf(");
conditional.append(thenValue.getText());
conditional.append("):");
conditional.append(getExpressionText(elseValue));
conditional.append(".valueOf(").append(thenValue.getText()).append("):");
conditional.append(getExpressionText(elseValue, false));
}
else if (elseType instanceof PsiPrimitiveType &&
!PsiType.NULL.equals(elseType) &&
!(thenType instanceof PsiPrimitiveType) &&
!(requiredType instanceof PsiPrimitiveType)) {
// prevent unboxing of boxed value to preserve semantics (IDEADEV-36008)
conditional.append(getExpressionText(thenValue));
conditional.append(getExpressionText(thenValue, false));
conditional.append(':');
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)elseType;
conditional.append(primitiveType.getBoxedTypeName());
conditional.append(".valueOf(");
conditional.append(elseValue.getText());
conditional.append(')');
conditional.append(".valueOf(").append(elseValue.getText()).append(')');
}
else {
conditional.append(getExpressionText(thenValue));
conditional.append(getExpressionText(thenValue, false));
conditional.append(':');
conditional.append(getExpressionText(elseValue));
conditional.append(getExpressionText(elseValue, false));
}
return conditional.toString();
}
@@ -230,9 +223,12 @@ public class ReplaceIfWithConditionalIntention extends Intention {
return thenValue;
}
private static String getExpressionText(PsiExpression expression) {
if (ParenthesesUtils.getPrecedence(expression) <=
ParenthesesUtils.CONDITIONAL_PRECEDENCE) {
private static String getExpressionText(PsiExpression expression, boolean isCondition) {
final int precedence = ParenthesesUtils.getPrecedence(expression);
if (precedence <= ParenthesesUtils.CONDITIONAL_PRECEDENCE) {
if (isCondition && precedence == ParenthesesUtils.CONDITIONAL_PRECEDENCE) {
return '(' + expression.getText() + ')';
}
return expression.getText();
}
else {
@@ -0,0 +1,16 @@
package com.siyeh.ipp.trivialif.replaceIfWithConditional;
class ConditionalCondition {
String s;
String t;
public boolean equals(Object other) {
if (!(other instanceof ConditionalCondition)) return false;
final ConditionalCondition condition = (ConditionalCondition)other;
if<caret> (s != null ? !s.equals(condition.s) : condition.s != null) return false;
return t.equals(condition.t);
}
}
@@ -0,0 +1,15 @@
package com.siyeh.ipp.trivialif.replaceIfWithConditional;
class ConditionalCondition {
String s;
String t;
public boolean equals(Object other) {
if (!(other instanceof ConditionalCondition)) return false;
final ConditionalCondition condition = (ConditionalCondition)other;
return (s != null ? !s.equals(condition.s) : condition.s != null) ? false : t.equals(condition.t);
}
}
@@ -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.
@@ -18,19 +18,15 @@ package com.siyeh.ipp.trivialif;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.IPPTestCase;
/**
* @see com.siyeh.ipp.trivialif.ReplaceIfWithConditionalIntention
*/
public class ReplaceIfWithConditionalIntentionTest extends IPPTestCase {
public void testReturnValueWithDiamonds() {
doTest();
}
public void testReplaceableAssignmentsWithDiamonds() {
doTest();
}
public void testReplaceableAssignmentsWithDiamondsLeave() {
doTest();
}
public void testReturnValueWithDiamonds() { doTest(); }
public void testReplaceableAssignmentsWithDiamonds() { doTest(); }
public void testReplaceableAssignmentsWithDiamondsLeave() { doTest(); }
public void testConditionalCondition() { doTest(); }
@Override
protected String getIntentionName() {
+2
View File
@@ -148,6 +148,8 @@
<projectService serviceInterface="git4idea.branch.GitBrancher"
serviceImplementation="git4idea.branch.GitBrancherImpl"/>
<projectService serviceImplementation="git4idea.log.GitContentRevisionFactory" />
<applicationService serviceImplementation="git4idea.history.wholeTree.GitCommitsSequentialIndex"
serviceInterface="git4idea.history.wholeTree.GitCommitsSequentially"/>
<applicationService serviceInterface="git4idea.config.GitVcsApplicationSettings"
+7 -2
View File
@@ -15,10 +15,12 @@
*/
package git4idea;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.impl.VcsFullCommitDetailsImpl;
import git4idea.log.GitContentRevisionFactory;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -30,10 +32,13 @@ import java.util.List;
*/
public final class GitCommit extends VcsFullCommitDetailsImpl {
public GitCommit(@NotNull Hash hash, @NotNull List<Hash> parents, long authorTime, @NotNull VirtualFile root, @NotNull String subject,
public GitCommit(final Project project, @NotNull Hash hash, @NotNull List<Hash> parents, long authorTime, @NotNull VirtualFile root,
@NotNull String subject,
@NotNull String authorName,
@NotNull String authorEmail, @NotNull String message, @NotNull String committerName, @NotNull String committerEmail,
long commitTime, @NotNull List<Change> changes) {
super(hash, parents, authorTime, root, subject, authorName, authorEmail, message, committerName, committerEmail, commitTime, changes);
super(hash, parents, authorTime, root, subject, authorName, authorEmail, message, committerName, committerEmail, commitTime, changes,
GitContentRevisionFactory.getInstance(project));
}
}
@@ -199,12 +199,12 @@ public class GitContentRevision implements ContentRevision {
}
public static ContentRevision createRevision(@NotNull final VirtualFile file, @Nullable final VcsRevisionNumber revisionNumber,
@NotNull final Project project) throws VcsException {
@NotNull final Project project) {
return createRevision(file, revisionNumber, project, null);
}
public static ContentRevision createRevision(@NotNull final VirtualFile file, @Nullable final VcsRevisionNumber revisionNumber,
@NotNull final Project project, @Nullable final Charset charset) throws VcsException {
@NotNull final Project project, @Nullable final Charset charset) {
final FilePathImpl filePath = new FilePathImpl(file);
return createRevision(filePath, revisionNumber, project, charset);
}
@@ -39,6 +39,7 @@ import git4idea.config.GitVcsSettings;
import git4idea.history.browser.GitHeavyCommit;
import git4idea.history.wholeTree.AbstractHash;
import git4idea.history.wholeTree.GitCommitDetailsProvider;
import git4idea.log.GitContentRevisionFactory;
import git4idea.repo.GitRepository;
import icons.Git4ideaIcons;
import org.jetbrains.annotations.NotNull;
@@ -166,14 +167,14 @@ public class GitCherryPickAction extends DumbAwareAction {
// TODO remove after removing the old Vcs Log implementation
@Nullable
private List<? extends VcsFullCommitDetails> getSelectedCommits(AnActionEvent e) {
List<GitHeavyCommit> commits = e.getData(GitVcs.SELECTED_COMMITS);
if (commits != null) {
return convertHeavyCommitToFullDetails(commits);
}
final Project project = e.getProject();
if (project == null) {
return null;
}
List<GitHeavyCommit> commits = e.getData(GitVcs.SELECTED_COMMITS);
if (commits != null) {
return convertHeavyCommitToFullDetails(commits, project);
}
final VcsLog log = getVcsLog(project);
if (log == null) {
return null;
@@ -197,7 +198,7 @@ public class GitCherryPickAction extends DumbAwareAction {
return selectedDetails;
}
private static List<? extends VcsFullCommitDetails> convertHeavyCommitToFullDetails(List<GitHeavyCommit> commits) {
private static List<? extends VcsFullCommitDetails> convertHeavyCommitToFullDetails(List<GitHeavyCommit> commits, final Project project) {
return ContainerUtil.map(commits, new Function<GitHeavyCommit, VcsFullCommitDetails>() {
@Override
public VcsFullCommitDetails fun(GitHeavyCommit commit) {
@@ -211,7 +212,7 @@ public class GitCherryPickAction extends DumbAwareAction {
return factory.createFullDetails(
factory.createHash(commit.getHash().getValue()), parents, commit.getAuthorTime(), commit.getRoot(), commit.getSubject(),
commit.getAuthor(), commit.getAuthorEmail(), commit.getDescription(), commit.getCommitter(), commit.getCommitterEmail(),
commit.getDate().getTime(), commit.getChanges()
commit.getDate().getTime(), commit.getChanges(), GitContentRevisionFactory.getInstance(project)
);
}
});
@@ -458,6 +458,7 @@ public abstract class GitHandler {
startHandlingStreams();
}
catch (Throwable t) {
LOG.error(t);
cleanupEnv();
myListeners.getMulticaster().startFailed(t);
}
@@ -711,7 +711,7 @@ public class GitHistoryUtils {
return HashImpl.build(hash);
}
});
return new GitCommit(HashImpl.build(record.getHash()), parents, record.getAuthorTimeStamp(), root, record.getSubject(),
return new GitCommit(project, HashImpl.build(record.getHash()), parents, record.getAuthorTimeStamp(), root, record.getSubject(),
record.getAuthorName(), record.getAuthorEmail(), record.getFullMessage(), record.getCommitterName(),
record.getCommitterEmail(), record.getLongTimeStamp(),
record.parseChanges(project, root));
@@ -0,0 +1,57 @@
/*
* 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 git4idea.log;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.ContentRevisionFactory;
import com.intellij.vcs.log.Hash;
import git4idea.GitContentRevision;
import git4idea.GitRevisionNumber;
import org.jetbrains.annotations.NotNull;
import java.io.File;
public class GitContentRevisionFactory extends ContentRevisionFactory {
@NotNull private final Project myProject;
@SuppressWarnings("UnusedDeclaration")
private GitContentRevisionFactory(@NotNull Project project) {
myProject = project;
}
public static ContentRevisionFactory getInstance(Project project) {
return ServiceManager.getService(project, GitContentRevisionFactory.class);
}
@NotNull
@Override
public ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash) {
return GitContentRevision.createRevision(file, new GitRevisionNumber(hash.asString()), myProject);
}
@NotNull
@Override
public ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash) {
return GitContentRevision.createRevision(new FilePathImpl(new File(path), false),
new GitRevisionNumber(hash.asString()), myProject, null);
}
}
@@ -39,6 +39,7 @@ import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import git4idea.cherrypick.GitCherryPicker;
import git4idea.config.GitVersionSpecialty;
import git4idea.log.GitContentRevisionFactory;
import java.util.*;
@@ -263,7 +264,7 @@ public class GitCherryPickStepdefs {
changes.add(new Change(null, new MockContentRevision(new FilePathImpl(new MockVirtualFile("name")), VcsRevisionNumber.NULL)));
return ServiceManager.getService(VcsLogObjectsFactory.class).createFullDetails(
HashImpl.build(hash), Collections.<Hash>emptyList(), 0, NullVirtualFile.INSTANCE, message, "John Smith", "john@mail.com", message,
"John Smith", "john@mail.com", 0, changes);
"John Smith", "john@mail.com", 0, changes, GitContentRevisionFactory.getInstance(myProject));
}
}
@@ -204,7 +204,7 @@ public class ImportMavenRepositoriesTask implements Runnable {
if (uri.getScheme() != null && StringUtil.startsWith(uri.getScheme(), "http")) return uri;
}
}
catch (URISyntaxException e) {
catch (URISyntaxException ignored) {
// ignore it
}
@@ -219,7 +219,7 @@ public class ImportMavenRepositoriesTask implements Runnable {
if (uri.getScheme() != null && StringUtil.startsWith("http", uri.getScheme())) return uri;
}
}
catch (URISyntaxException e) {
catch (URISyntaxException ignored) {
// ignore it
}
@@ -19,11 +19,9 @@ import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
@@ -91,12 +89,6 @@ class AddGradleDslDependencyActionHandler implements CodeInsightActionHandler {
}
}
}
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
Document document = documentManager.getDocument(file);
if (document != null) {
documentManager.commitDocument(document);
}
}
}.execute();
}
@@ -0,0 +1,277 @@
/*
* 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 org.jetbrains.plugins.groovy.refactoring.introduce;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
import java.util.List;
/**
* Created by Max Medvedev on 10/28/13
*/
public abstract class GrAbstractInplaceIntroducer<Settings extends GrIntroduceSettings> extends AbstractInplaceIntroducer<GrVariable, PsiElement> {
private SmartTypePointer myTypePointer;
private OccurrencesChooser.ReplaceChoice myReplaceChoice;
private RangeMarker myVarMarker;
private final PsiFile myFile;
private final GrIntroduceContext myContext;
public GrAbstractInplaceIntroducer(String title,
OccurrencesChooser.ReplaceChoice replaceChoice,
GrIntroduceContext context) {
super(context.getProject(), context.getEditor(), context.getExpression(), context.getVar(), context.getOccurrences(), title, GroovyFileType.GROOVY_FILE_TYPE);
myReplaceChoice = replaceChoice;
myContext = context;
myFile = context.getPlace().getContainingFile();
}
public GrIntroduceContext getContext() {
return myContext;
}
@Override
public void setReplaceAllOccurrences(boolean allOccurrences) {
throw new IncorrectOperationException("don't invoke this method");
}
@Override
public GrExpression restoreExpression(PsiFile containingFile, GrVariable variable, RangeMarker marker, String exprText) {
if (exprText == null) return null;
if (variable == null || !variable.isValid()) return null;
final PsiElement refVariableElement = containingFile.findElementAt(marker.getStartOffset());
final PsiElement refVariableElementParent = refVariableElement != null ? refVariableElement.getParent() : null;
GrExpression expression =
refVariableElementParent instanceof GrNewExpression && refVariableElement.getNode().getElementType() == GroovyTokenTypes.kNEW
? (GrNewExpression)refVariableElementParent
: PsiTreeUtil.getParentOfType(refVariableElement, GrReferenceExpression.class);
if (expression instanceof GrReferenceExpression && !(expression.getParent() instanceof GrMethodCall)) {
final String referenceName = ((GrReferenceExpression)expression).getReferenceName();
if (((GrReferenceExpression)expression).resolve() == variable ||
Comparing.strEqual(variable.getName(), referenceName) ||
Comparing.strEqual(exprText, referenceName)) {
return (GrExpression)expression
.replace(GroovyPsiElementFactory.getInstance(myProject).createExpressionFromText(exprText, variable));
}
}
if (expression == null) {
expression = PsiTreeUtil.getParentOfType(refVariableElement, GrExpression.class);
}
while (expression instanceof GrReferenceExpression) {
final PsiElement parent = expression.getParent();
if (parent instanceof GrMethodCallExpression) {
if (parent.getText().equals(exprText)) return (GrExpression)parent;
}
if (parent instanceof GrExpression) {
expression = (GrExpression)parent;
if (expression.getText().equals(exprText)) {
return expression;
}
}
else {
return null;
}
}
if (expression != null && expression.isValid() && expression.getText().equals(exprText)) {
return expression;
}
if (refVariableElementParent instanceof GrExpression && refVariableElementParent.getText().equals(exprText)) {
return (GrExpression)refVariableElementParent;
}
return null;
}
@Override
protected void updateTitle(@Nullable GrVariable variable, String value) {
if (variable == null) {
super.updateTitle(variable, value);
}
else {
final String variableText = variable.getParent().getText();
final PsiElement identifier = variable.getNameIdentifierGroovy();
final int startOffsetInParent = identifier.getStartOffsetInParent() + variable.getStartOffsetInParent();
setPreviewText(
variableText.substring(0, startOffsetInParent) + value + variableText.substring(startOffsetInParent + identifier.getTextLength()));
revalidate();
}
}
@Override
protected void updateTitle(@Nullable GrVariable variable) {
if (variable == null) return;
setPreviewText(variable.getParent().getText());
revalidate();
}
@Nullable
@Override
protected PsiElement getNameIdentifier() {
return ((GrVariable)myElementToRename).getNameIdentifierGroovy();
}
@Override
protected GrVariable getVariable() {
if (myVarMarker == null) return null;
int offset = myVarMarker.getStartOffset();
PsiElement at = myFile.findElementAt(offset);
GrVariable var = PsiTreeUtil.getParentOfType(at, GrVariable.class);
return var;
}
@Override
protected void performIntroduce() {
final List<RangeMarker> markers = getOccurrenceMarkers();
GrIntroduceContext context = new GrIntroduceContext() {
@NotNull
@Override
public Project getProject() {
return myProject;
}
@Override
public Editor getEditor() {
return myEditor;
}
@Nullable
@Override
public GrExpression getExpression() {
return (GrExpression)getExpr();
}
@Nullable
@Override
public GrVariable getVar() {
return getLocalVariable();
}
@Nullable
@Override
public StringPartInfo getStringPart() {
return null;
}
@NotNull
@Override
public PsiElement[] getOccurrences() {
List<PsiElement> result = ContainerUtil.map(markers, new Function<RangeMarker, PsiElement>() {
@Override
public PsiElement fun(RangeMarker marker) {
return GroovyRefactoringUtil.findElementInRange(myFile, marker.getStartOffset(), marker.getEndOffset(), GrExpression.class);
}
});
return PsiUtilCore.toPsiElementArray(result);
}
@Override
public PsiElement getScope() {
return myScope;
}
@NotNull
@Override
public PsiElement getPlace() {
GrExpression expression = getExpression();
return expression != null ? expression : getLocalVariable();
}
};
runRefactoring(context, getSettings(), true);
}
@Nullable
@Override
protected GrVariable createFieldToStartTemplateOn(boolean replaceAll, String[] names) {
final Settings settings = getInitialSettingsForInplace(myContext, myReplaceChoice, names);
if (settings == null) return null;
SmartPsiElementPointer<GrVariable> pointer = ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrVariable>>() {
@Override
public SmartPsiElementPointer<GrVariable> compute() {
GrVariable var = runRefactoring(myContext, settings, false);
return var != null ? SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(var) : null;
}
});
if (pointer != null) {
GrVariable var = pointer.getElement();
if (var != null) {
myVarMarker = myContext.getEditor().getDocument().createRangeMarker(var.getTextRange());
}
return var;
}
else {
return null;
}
}
protected abstract GrVariable runRefactoring(GrIntroduceContext context, Settings settings, boolean processUsages);
@Nullable
protected abstract Settings getInitialSettingsForInplace(@NotNull GrIntroduceContext context,
@NotNull OccurrencesChooser.ReplaceChoice choice,
String[] names);
@Override
public boolean isReplaceAllOccurrences() {
return myReplaceChoice != OccurrencesChooser.ReplaceChoice.NO || myContext.getOccurrences().length == 1;
}
protected abstract Settings getSettings();
@Override
protected void restoreState(GrVariable psiField) {
PsiType declaredType = psiField.getDeclaredType();
myTypePointer = declaredType != null ? SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(declaredType) : null;
super.restoreState(psiField);
}
@Nullable
protected PsiType getSelectedType() {
return myTypePointer != null ? myTypePointer.getType() : null;
}
}
@@ -21,7 +21,6 @@ import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -32,7 +31,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.wm.WindowManager;
@@ -77,7 +75,7 @@ import java.util.*;
import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses;
/**
* @author Maxim.Medvedev
* Created by Max Medvedev on 10/29/13
*/
public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSettings, Scope extends PsiElement> implements RefactoringActionHandler {
private static final Logger LOG = Logger.getInstance(GrIntroduceHandlerBase.class);
@@ -144,15 +142,8 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
@Nullable
public abstract GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull Settings settings);
protected abstract GrInplaceIntroducer getIntroducer(@NotNull GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull Settings settings,
@NotNull List<RangeMarker> occurrenceMarkers,
RangeMarker varRangeMarker,
@Nullable RangeMarker expressionRangeMarker,
@Nullable RangeMarker stringPartRangeMarker);
protected abstract Settings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice);
protected abstract GrAbstractInplaceIntroducer<Settings> getIntroducer(@NotNull GrIntroduceContext context,
OccurrencesChooser.ReplaceChoice choice);
public static Map<OccurrencesChooser.ReplaceChoice, List<Object>> fillChoice(GrIntroduceContext context) {
HashMap<OccurrencesChooser.ReplaceChoice, List<Object>> map = ContainerUtil.newLinkedHashMap();
@@ -296,7 +287,8 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
};
if (scopes.length == 0) {
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage( getRefactoringName() + "is not available in current scope"),
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle
.getCannotRefactorMessage(getRefactoringName() + "is not available in current scope"),
getRefactoringName(), getHelpID());
}
else if (scopes.length == 1) {
@@ -310,11 +302,11 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
protected abstract void showScopeChooser(Scope[] scopes, Pass<Scope> callback, Editor editor);
public GrIntroduceContext getContext(@NotNull Project project,
@NotNull Editor editor,
@Nullable GrExpression expression,
@Nullable GrVariable variable,
@Nullable StringPartInfo stringPart,
@NotNull PsiElement scope) {
@NotNull Editor editor,
@Nullable GrExpression expression,
@Nullable GrVariable variable,
@Nullable StringPartInfo stringPart,
@NotNull PsiElement scope) {
if (variable != null) {
final List<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
@@ -348,48 +340,6 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
checkOccurrences(context.getOccurrences());
final boolean isInplace = isInplace(context.getEditor(), context.getPlace());
Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
@Override
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
final Settings settings = isInplace ? getSettingsForInplace(context, choice) : showDialog(context);
if (settings == null) return;
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
public void run() {
List<RangeMarker> occurrences = ContainerUtil.newArrayList();
Document document = editor.getDocument();
for (PsiElement element : context.getOccurrences()) {
occurrences.add(createRange(document, element));
}
RangeMarker expressionRangeMarker = createRange(document, context.getExpression());
RangeMarker stringPartRangeMarker = createRange(document, context.getStringPart());
RangeMarker varRangeMarker = createRange(document, context.getVar());
SmartPsiElementPointer<GrVariable> pointer =
ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrVariable>>() {
@Override
public SmartPsiElementPointer<GrVariable> compute() {
GrVariable var = runRefactoring(context, settings);
return var != null
? SmartPointerManager.getInstance(context.getProject()).createSmartPsiElementPointer(var)
: null;
}
});
GrVariable var = pointer != null ? pointer.getElement() : null;
if (isInplace && var != null) {
GrInplaceIntroducer introducer = getIntroducer(var, context, settings, occurrences, varRangeMarker, expressionRangeMarker, stringPartRangeMarker);
LinkedHashSet<String> suggestions = introducer.suggestNames(context);
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
introducer.performInplaceRefactoring(suggestions);
}
}
}, getRefactoringName(), getRefactoringName());
}
};
if (isInplace(context.getEditor(), context.getPlace())) {
Map<OccurrencesChooser.ReplaceChoice, List<Object>> occurrencesMap = fillChoice(context);
new OccurrencesChooser<Object>(editor) {
@@ -405,17 +355,28 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
return null;
}
}
}.showChooser(callback, occurrencesMap);
}.showChooser(new Pass<OccurrencesChooser.ReplaceChoice>() {
@Override
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
getIntroducer(context, choice).startInplaceIntroduceTemplate();
}
}, occurrencesMap);
}
else {
callback.pass(null);
final Settings settings = showDialog(context);
if (settings == null) return false;
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
runRefactoring(context, settings);
}
});
}
return true;
}
catch (GrRefactoringError e) {
CommonRefactoringUtil
.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID());
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID());
return false;
}
}
@@ -15,127 +15,118 @@
*/
package org.jetbrains.plugins.groovy.refactoring.introduce.constant;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.introduceField.IntroduceConstantHandler;
import com.intellij.ui.components.JBCheckBox;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator;
import javax.swing.*;
import java.util.LinkedHashSet;
import java.util.List;
/**
* Created by Max Medvedev on 8/29/13
*/
public class GrInplaceConstantIntroducer extends GrInplaceIntroducer {
public class GrInplaceConstantIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceConstantSettings> {
private final GrInplaceIntroduceConstantPanel myPanel;
private final GrIntroduceContext myContext;
private final RangeMarker myExpressionRangeMarker;
private final RangeMarker myStringPartRangeMarker;
private final boolean myReplaceAll;
private String[] mySuggestedNames;
public GrInplaceConstantIntroducer(GrVariable var,
GrIntroduceContext context,
List<RangeMarker> occurrences,
boolean replaceAllOccurrences,
RangeMarker expressionRangeMarker,
RangeMarker stringPartRangeMarker) {
super(var, context.getEditor(), context.getProject(), GrIntroduceConstantHandler.REFACTORING_NAME, occurrences, context.getPlace());
public GrInplaceConstantIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
super(IntroduceConstantHandler.REFACTORING_NAME, choice, context);
myContext = context;
myReplaceAll = replaceAllOccurrences;
myExpressionRangeMarker = expressionRangeMarker;
myStringPartRangeMarker = stringPartRangeMarker;
myPanel = new GrInplaceIntroduceConstantPanel();
mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(context),
true);
}
@Override
public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames(
context.getExpression(),
new GroovyInplaceFieldValidator(context),
getVariable().hasModifierProperty(PsiModifier.STATIC))
);
protected String getActionName() {
return null;
}
@Override
protected void moveOffsetAfter(boolean success) {
if (success) {
final GrVariable field = getVariable();
assert field != null;
GrIntroduceConstantProcessor processor = new GrIntroduceConstantProcessor(generateContext(), generateSettings()) {
@Override
protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) {
return (GrVariableDeclaration)field.getParent();
}
@Override
protected boolean checkErrors(@NotNull PsiClass targetClass) {
return false;
}
};
processor.run();
}
super.moveOffsetAfter(success);
}
private GrIntroduceContext generateContext() {
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
List<PsiElement> occurrences = ContainerUtil.newArrayList();
for (RangeMarker marker : occurrenceMarkers) {
ContainerUtil.addIfNotNull(occurrences, findExpression(marker));
}
GrExpression expr = null;
if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker);
if (myStringPartRangeMarker != null) {
expr = findExpressionFromStringPartMarker(myStringPartRangeMarker);
occurrences.add(expr);
}
return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray(
occurrences), myContext.getScope());
protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
return mySuggestedNames;
}
@Nullable
private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) {
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
if (file == null) return null;
PsiElement leaf = file.findElementAt(marker.getStartOffset());
GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class);
if (binary != null) {
return binary.getRightOperand();
@Override
protected JComponent getComponent() {
return myPanel.getRootPane();
}
@Override
protected void saveSettings(@NotNull GrVariable variable) {
}
@Override
protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceConstantSettings settings, boolean processUsages) {
if (processUsages) {
return new GrIntroduceConstantProcessor(context, settings).run();
}
else {
PsiElement scope = context.getScope();
return new GrIntroduceConstantProcessor(context, settings).addDeclaration(scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope).getVariables()[0];
}
return null;
}
@Nullable
private GrExpression findExpression(@NotNull RangeMarker marker) {
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
if (file == null) return null;
PsiElement leaf = file.findElementAt(marker.getStartOffset());
if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) {
return (GrExpression)leaf.getParent();
}
return null;
@Override
protected GrIntroduceConstantSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context,
@NotNull final OccurrencesChooser.ReplaceChoice choice,
final String[] names) {
return new GrIntroduceConstantSettings() {
@Override
public String getVisibilityModifier() {
return PsiModifier.PUBLIC;
}
@Nullable
@Override
public PsiClass getTargetClass() {
return (PsiClass)context.getScope();
}
@Nullable
@Override
public String getName() {
return names[0];
}
@Override
public boolean replaceAllOccurrences() {
return isReplaceAllOccurrences();
}
@Nullable
@Override
public PsiType getSelectedType() {
GrExpression expression = context.getExpression();
GrVariable var = context.getVar();
StringPartInfo stringPart = context.getStringPart();
return var != null ? var.getDeclaredType() :
expression != null ? expression.getType() :
stringPart != null ? stringPart.getLiteral().getType() :
null;
}
};
}
private GrIntroduceConstantSettings generateSettings() {
@Override
protected GrIntroduceConstantSettings getSettings() {
return new GrIntroduceConstantSettings() {
@Override
public String getVisibilityModifier() {
@@ -145,18 +136,18 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer {
@Nullable
@Override
public String getName() {
return getVariable().getName();
return getInputName();
}
@Override
public boolean replaceAllOccurrences() {
return myReplaceAll;
return isReplaceAllOccurrences();
}
@Nullable
@Override
public PsiType getSelectedType() {
return getVariable().getDeclaredType();
return GrInplaceConstantIntroducer.this.getSelectedType();
}
@Nullable
@@ -167,17 +158,30 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer {
};
}
@Nullable
@Override
protected JComponent getComponent() {
//return myPanel.getRootPane();
return null;
}
@Nullable
@Override
protected PsiElement checkLocalScope() {
return getVariable().getContainingFile();
return ((PsiField)getVariable()).getContainingClass();
}
/**
* Created by Max Medvedev on 8/29/13
*/
public class GrInplaceIntroduceConstantPanel {
private JBCheckBox myMoveToAnotherClassJBCheckBox;
private JPanel myRootPane;
private JComponent myPreview;
public boolean isMoveToAnotherClass() {
return myMoveToAnotherClassJBCheckBox.isSelected();
}
public JComponent getRootPane() {
return myRootPane;
}
private void createUIComponents() {
myPreview = getPreviewComponent();
}
}
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrInplaceIntroduceConstantPanel">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrInplaceConstantIntroducer.GrInplaceIntroduceConstantPanel">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
@@ -10,17 +10,24 @@
<children>
<vspacer id="3c553">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="1ff44" class="com.intellij.ui.components.JBCheckBox" binding="myMoveToAnotherClassJBCheckBox" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<focusable value="false"/>
<requestFocusEnabled value="true"/>
<text value="&amp;Move to another class"/>
</properties>
</component>
<component id="3e5fd" class="javax.swing.JComponent" binding="myPreview" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</component>
</children>
</grid>
</form>
@@ -15,7 +15,6 @@
*/
package org.jetbrains.plugins.groovy.refactoring.introduce.constant;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.HelpID;
@@ -27,16 +26,11 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import org.jetbrains.plugins.groovy.refactoring.introduce.*;
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrFieldNameSuggester;
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator;
import java.util.List;
/**
* @author Maxim.Medvedev
@@ -99,65 +93,9 @@ public class GrIntroduceConstantHandler extends GrIntroduceFieldHandlerBase<GrIn
}
@Override
protected GrInplaceIntroducer getIntroducer(@NotNull final GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull GrIntroduceConstantSettings settings,
@NotNull List<RangeMarker> occurrenceMarkers,
RangeMarker varRangeMarker, RangeMarker expressionRangeMarker,
RangeMarker stringPartRangeMarker) {
if (varRangeMarker != null) {
context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset());
}
else if (expressionRangeMarker != null) {
context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset());
}
else if (stringPartRangeMarker != null) {
int offset = stringPartRangeMarker.getStartOffset();
PsiElement at = var.getContainingFile().findElementAt(offset);
GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand();
context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset());
}
return new GrInplaceConstantIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker, stringPartRangeMarker);
}
@Override
protected GrIntroduceConstantSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) {
return new GrIntroduceConstantSettings() {
@Override
public String getVisibilityModifier() {
return PsiModifier.PUBLIC;
}
@Nullable
@Override
public PsiClass getTargetClass() {
return (PsiClass)context.getScope();
}
@Nullable
@Override
public String getName() {
return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next();
}
@Override
public boolean replaceAllOccurrences() {
return choice == OccurrencesChooser.ReplaceChoice.ALL;
}
@Nullable
@Override
public PsiType getSelectedType() {
GrExpression expression = context.getExpression();
GrVariable var = context.getVar();
StringPartInfo stringPart = context.getStringPart();
return var != null ? var.getDeclaredType() :
expression != null ? expression.getType() :
stringPart != null ? stringPart.getLiteral().getType() :
null;
}
};
protected GrAbstractInplaceIntroducer<GrIntroduceConstantSettings> getIntroducer(@NotNull GrIntroduceContext context,
OccurrencesChooser.ReplaceChoice choice) {
return new GrInplaceConstantIntroducer(context, choice);
}
private static class ConstantChecker extends GroovyRecursiveElementVisitor {
@@ -69,8 +69,7 @@ public class GrIntroduceConstantProcessor {
return null;
}
final GrVariableDeclaration rawDeclaration = createField(targetClass);
final GrVariableDeclaration declaration = addDeclaration(targetClass, rawDeclaration);
final GrVariableDeclaration declaration = addDeclaration(targetClass);
final GrField field = (GrField)declaration.getVariables()[0];
if (context.getVar() != null) {
@@ -102,7 +101,8 @@ public class GrIntroduceConstantProcessor {
context.getEditor().getSelectionModel().removeSelection();
}
protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) {
protected GrVariableDeclaration addDeclaration(PsiClass targetClass) {
GrVariableDeclaration declaration = createField(targetClass);
final GrVariableDeclaration added;
if (targetClass instanceof GrEnumTypeDefinition) {
final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList();
@@ -17,140 +17,133 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.field;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.introduce.inplace.KeyboardComboSwitcher;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
/**
* @author Max Medvedev
*/
public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
private final GrInplaceIntroduceFieldPanel myPanel;
private final GrIntroduceContext myContext;
private final RangeMarker myExpressionRangeMarker;
private final RangeMarker myStringPartRangeMarker;
private final GrExpression myInitializer;
public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceFieldSettings> {
private GrInplaceIntroduceFieldPanel myPanel;
private final GrFinalListener finalListener;
private final boolean myReplaceAll;
private String[] mySuggestedNames;
private boolean myIsStatic;
@Nullable
@Override
protected PsiElement checkLocalScope() {
return getVariable().getContainingFile();
return ((PsiField)getVariable()).getContainingClass();
}
public GrInplaceFieldIntroducer(GrVariable var,
GrIntroduceContext context,
List<RangeMarker> occurrences,
boolean replaceAll,
@Nullable RangeMarker expressionRangeMarker,
@Nullable RangeMarker stringPartRangeMarker,
GrExpression initializer) {
super(var, context.getEditor(), context.getProject(), IntroduceFieldHandler.REFACTORING_NAME, occurrences, context.getPlace());
myContext = context;
myReplaceAll = replaceAll;
myExpressionRangeMarker = expressionRangeMarker;
myStringPartRangeMarker = stringPartRangeMarker;
myInitializer = initializer;
myPanel = new GrInplaceIntroduceFieldPanel(context.getProject(),
GrIntroduceFieldHandler.getApplicableInitPlaces(context, replaceAll));
public GrInplaceFieldIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
super(IntroduceFieldHandler.REFACTORING_NAME, choice, context);
finalListener = new GrFinalListener(myEditor);
mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false);
}
@Override
protected void moveOffsetAfter(boolean success) {
if (success) {
final GrVariable field = getVariable();
assert field != null;
GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(generateContext(), generateSettings(), false) {
@NotNull
@Override
protected GrExpression getInitializer() {
return myInitializer;
}
@NotNull
@Override
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) {
return (GrVariableDeclaration)field.getParent();
}
};
processor.run();
}
super.moveOffsetAfter(success);
}
private GrIntroduceContext generateContext() {
final List<RangeMarker> occurrenceMarkers = getOccurrenceMarkers();
List<PsiElement> occurrences = ContainerUtil.newArrayList();
for (RangeMarker marker : occurrenceMarkers) {
ContainerUtil.addIfNotNull(occurrences, findExpression(marker));
}
GrExpression expr = null;
if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker);
if (myStringPartRangeMarker != null) {
expr = findExpressionFromStringPartMarker(myStringPartRangeMarker);
occurrences.add(expr);
}
return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray(
occurrences), myContext.getScope());
protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings, boolean processUsages) {
GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(context, settings);
return processUsages ? processor.run()
: processor.insertField((PsiClass)context.getScope()).getVariables()[0];
}
@Nullable
private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) {
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
if (file == null) return null;
PsiElement leaf = file.findElementAt(marker.getStartOffset());
GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class);
if (binary != null) {
return binary.getRightOperand();
}
return null;
@Override
protected GrIntroduceFieldSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context,
@NotNull final OccurrencesChooser.ReplaceChoice choice,
final String[] names) {
return new GrIntroduceFieldSettings() {
@Override
public boolean declareFinal() {
return false;
}
@Override
public Init initializeIn() {
return Init.FIELD_DECLARATION;
}
@Override
public String getVisibilityModifier() {
return PsiModifier.PRIVATE;
}
@Override
public boolean isStatic() {
boolean hasInstanceInScope = true;
PsiClass clazz = (PsiClass)context.getScope();
if (replaceAllOccurrences()) {
for (PsiElement occurrence : context.getOccurrences()) {
if (!PsiUtil.hasEnclosingInstanceInScope(clazz, occurrence, false)) {
hasInstanceInScope = false;
break;
}
}
}
else if (context.getExpression() != null) {
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getExpression(), false);
}
else if (context.getStringPart() != null) {
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getStringPart().getLiteral(), false);
}
return !hasInstanceInScope;
}
@Override
public boolean removeLocalVar() {
return context.getVar() != null;
}
@Nullable
@Override
public String getName() {
return names[0];
}
@Override
public boolean replaceAllOccurrences() {
return context.getVar() != null || choice == OccurrencesChooser.ReplaceChoice.ALL;
}
@Nullable
@Override
public PsiType getSelectedType() {
GrExpression expression = context.getExpression();
GrVariable var = context.getVar();
StringPartInfo stringPart = context.getStringPart();
return var != null ? var.getDeclaredType() :
expression != null ? expression.getType() :
stringPart != null ? stringPart.getLiteral().getType() :
null;
}
};
}
@Nullable
private GrExpression findExpression(@NotNull RangeMarker marker) {
PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument());
if (file == null) return null;
PsiElement leaf = file.findElementAt(marker.getStartOffset());
if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) {
return (GrExpression)leaf.getParent();
}
return null;
}
private GrIntroduceFieldSettings generateSettings() {
@Override
protected GrIntroduceFieldSettings getSettings() {
return new GrIntroduceFieldSettings() {
@Override
public boolean declareFinal() {
@@ -169,7 +162,7 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
@Override
public boolean isStatic() {
return getVariable().hasModifierProperty(PsiModifier.STATIC);
return myIsStatic;
}
@Override
@@ -180,39 +173,57 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
@Nullable
@Override
public String getName() {
return getVariable().getName();
return getInputName();
}
@Override
public boolean replaceAllOccurrences() {
return myReplaceAll;
return isReplaceAllOccurrences();
}
@Nullable
@Override
public PsiType getSelectedType() {
return getVariable().getDeclaredType();
return GrInplaceFieldIntroducer.this.getSelectedType();
}
};
}
@Override
protected String getActionName() {
return IntroduceFieldHandler.REFACTORING_NAME;
}
@Override
protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
return mySuggestedNames;
}
@Override
protected void saveSettings(@NotNull GrVariable variable) {
}
@Override
protected void restoreState(GrVariable psiField) {
myIsStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
super.restoreState(psiField);
}
@Nullable
@Override
protected JComponent getComponent() {
myPanel = new GrInplaceIntroduceFieldPanel(myProject, GrIntroduceFieldHandler.getApplicableInitPlaces(getContext(), isReplaceAllOccurrences()));
return myPanel.getRootPane();
}
@Override
public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
return ContainerUtil.newLinkedHashSet(
GroovyNameSuggestionUtil.suggestVariableNames(myInitializer, new GroovyInplaceFieldValidator(context), false));
}
public class GrInplaceIntroduceFieldPanel {
private final Project myProject;
private JPanel myRootPane;
private JComboBox myInitCB;
private NonFocusableCheckBox myDeclareFinalCB;
private JComponent myPreview;
public GrInplaceIntroduceFieldPanel(Project project, EnumSet<GrIntroduceFieldSettings.Init> initPlaces) {
myProject = project;
@@ -251,5 +262,9 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer {
public boolean isFinal() {
return myDeclareFinalCB.isSelected();
}
private void createUIComponents() {
myPreview = getPreviewComponent();
}
}
}
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.refactoring.introduce.field.GrInplaceFieldIntroducer.GrInplaceIntroduceFieldPanel">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="540" height="63"/>
<xy x="20" y="20" width="540" height="88"/>
</constraints>
<properties/>
<border type="none"/>
@@ -11,7 +11,7 @@
<grid id="3dec1" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -35,13 +35,18 @@
</grid>
<component id="23db" class="com.intellij.ui.NonFocusableCheckBox" binding="myDeclareFinalCB">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<horizontalAlignment value="10"/>
<text value="Declare &amp;final"/>
</properties>
</component>
<component id="d8bd5" class="javax.swing.JComponent" binding="myPreview" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</component>
</children>
</grid>
</form>
@@ -16,25 +16,21 @@
package org.jetbrains.plugins.groovy.refactoring.introduce.field;
import com.intellij.codeInsight.TestFrameworks;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
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.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
@@ -100,133 +96,39 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase<GrIntro
@Override
public GrVariable runRefactoring(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings) {
return new GrIntroduceFieldProcessor(context, settings, isInplace(context.getEditor(), context.getPlace())).run();
return new GrIntroduceFieldProcessor(context, settings).run();
}
@Override
protected GrInplaceFieldIntroducer getIntroducer(@NotNull final GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull GrIntroduceFieldSettings settings,
@NotNull List<RangeMarker> occurrenceMarkers,
@Nullable RangeMarker varRangeMarker,
@Nullable RangeMarker expressionRangeMarker,
@Nullable RangeMarker stringPartRangeMarker) {
if (varRangeMarker != null) {
context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset());
}
else if (expressionRangeMarker != null) {
context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset());
}
else if (stringPartRangeMarker != null) {
int offset = stringPartRangeMarker.getStartOffset();
PsiElement at = var.getContainingFile().findElementAt(offset);
GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand();
context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset());
}
GrExpression initializer =
GroovyPsiElementFactory.getInstance(context.getProject()).createExpressionFromText(var.getInitializerGroovy().getText());
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
var.setInitializerGroovy(null);
}
});
return new GrInplaceFieldIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker,
stringPartRangeMarker, initializer);
@Override
protected GrAbstractInplaceIntroducer<GrIntroduceFieldSettings> getIntroducer(@NotNull GrIntroduceContext context,
OccurrencesChooser.ReplaceChoice choice) {
return new GrInplaceFieldIntroducer(context, choice);
}
static EnumSet<GrIntroduceFieldSettings.Init> getApplicableInitPlaces(GrIntroduceContext context, boolean replaceAll) {
EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION,
GrIntroduceFieldSettings.Init.CONSTRUCTOR);
EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION);
if (!(context.getScope() instanceof GroovyScriptClass || context.getScope() instanceof GroovyFileBase)) {
result.add(GrIntroduceFieldSettings.Init.CONSTRUCTOR);
}
GrTypeDefinition clazz = (GrTypeDefinition)context.getScope();
PsiElement scope = context.getScope();
if (replaceAll) {
PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), clazz);
PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), scope);
if (anchor != null) {
result.add(GrIntroduceFieldSettings.Init.CUR_METHOD);
}
}
if (TestFrameworks.getInstance().isTestClass(clazz)) {
if (scope instanceof GrTypeDefinition && TestFrameworks.getInstance().isTestClass((PsiClass)scope)) {
result.add(GrIntroduceFieldSettings.Init.SETUP_METHOD);
}
return result;
}
@Override
protected GrIntroduceFieldSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) {
return new GrIntroduceFieldSettings() {
@Override
public boolean declareFinal() {
return false;
}
@Override
public Init initializeIn() {
return Init.FIELD_DECLARATION;
}
@Override
public String getVisibilityModifier() {
return PsiModifier.PRIVATE;
}
@Override
public boolean isStatic() {
boolean hasInstanceInScope = true;
PsiClass clazz = (PsiClass)context.getScope();
if (replaceAllOccurrences()) {
for (PsiElement occurrence : context.getOccurrences()) {
if (!PsiUtil.hasEnclosingInstanceInScope(clazz, occurrence, false)) {
hasInstanceInScope = false;
break;
}
}
}
else if (context.getExpression() != null) {
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getExpression(), false);
}
else if (context.getStringPart() != null) {
hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getStringPart().getLiteral(), false);
}
return !hasInstanceInScope;
}
@Override
public boolean removeLocalVar() {
return context.getVar() != null;
}
@Nullable
@Override
public String getName() {
return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next();
}
@Override
public boolean replaceAllOccurrences() {
return context.getVar() != null || choice == OccurrencesChooser.ReplaceChoice.ALL;
}
@Nullable
@Override
public PsiType getSelectedType() {
GrExpression expression = context.getExpression();
GrVariable var = context.getVar();
StringPartInfo stringPart = context.getStringPart();
return var != null ? var.getDeclaredType() :
expression != null ? expression.getType() :
stringPart != null ? stringPart.getLiteral().getType() :
null;
}
};
}
@NotNull
@Override
protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) {
@@ -25,8 +25,10 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
@@ -62,19 +64,19 @@ public class GrIntroduceFieldProcessor {
private final GrIntroduceContext context;
private final GrIntroduceFieldSettings settings;
private boolean myForInplacePrepare;
public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings, boolean forInplacePrepare) {
public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context,
@NotNull GrIntroduceFieldSettings settings) {
this.context = context;
this.settings = settings;
myForInplacePrepare = forInplacePrepare;
}
public GrVariable run() {
final PsiClass targetClass = (PsiClass)context.getScope();
PsiElement scope = context.getScope();
final PsiClass targetClass = scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope;
if (targetClass == null) return null;
final GrVariableDeclaration declaration = insertField(targetClass, createField());
final GrVariableDeclaration declaration = insertField(targetClass);
final GrVariable field = declaration.getVariables()[0];
switch (settings.initializeIn()) {
@@ -119,7 +121,7 @@ public class GrIntroduceFieldProcessor {
else {
final GrExpression expression = context.getExpression();
assert expression != null;
if (!myForInplacePrepare && PsiUtil.isExpressionStatement(expression)) {
if (PsiUtil.isExpressionStatement(expression)) {
expression.delete();
}
else {
@@ -135,7 +137,8 @@ public class GrIntroduceFieldProcessor {
}
@NotNull
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) {
protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass) {
GrVariableDeclaration declaration = createField(targetClass);
if (targetClass instanceof GrEnumTypeDefinition) {
final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList();
return (GrVariableDeclaration)targetClass.addAfter(declaration, enumConstants);
@@ -304,7 +307,7 @@ public class GrIntroduceFieldProcessor {
}
if (replaced instanceof GrQualifiedReference<?>) {
org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster.shortenReference((GrQualifiedReference<?>)replaced);
GrReferenceAdjuster.shortenReference((GrQualifiedReference<?>)replaced);
}
if (isOriginal) {
updateCaretPosition(replaced);
@@ -326,13 +329,13 @@ public class GrIntroduceFieldProcessor {
return GroovyPsiElementFactory.getInstance(place.getProject()).createReferenceExpressionFromText(refText, place);
}
private GrVariableDeclaration createField() {
private GrVariableDeclaration createField(PsiClass targetClass) {
final String name = settings.getName();
final PsiType type = settings.getSelectedType();
final String modifier = settings.getVisibilityModifier();
List<String> modifiers = new ArrayList<String>();
if (context.getScope() instanceof GroovyScriptClass) {
if (targetClass instanceof GroovyScriptClass) {
modifiers.add("@" + GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD);
}
if (settings.isStatic()) modifiers.add(PsiModifier.STATIC);
@@ -341,7 +344,7 @@ public class GrIntroduceFieldProcessor {
final String[] arr_modifiers = ArrayUtil.toStringArray(modifiers);
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject());
if (context.getScope() instanceof GroovyScriptClass) {
if (targetClass instanceof GroovyScriptClass) {
return factory.createVariableDeclaration(arr_modifiers, ((GrExpression)null), type, name);
}
else {
@@ -16,25 +16,31 @@
package org.jetbrains.plugins.groovy.refactoring.introduce.variable;
import com.intellij.codeInsight.template.TemplateBuilderImpl;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint;
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings;
import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression;
@@ -42,30 +48,40 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedHashSet;
import java.util.List;
/**
* @author Max Medvedev
* Created by Max Medvedev on 10/29/13
*/
public class GrInplaceVariableIntroducer extends GrInplaceIntroducer {
public abstract class GrInplaceVariableIntroducer extends GrAbstractInplaceIntroducer<GroovyIntroduceVariableSettings> {
private JCheckBox myCanBeFinalCb;
public GrInplaceVariableIntroducer(GrVariable elementToRename,
Editor editor,
Project project,
String title,
List<RangeMarker> occurrences,
@Nullable PsiElement elementToIntroduce) {
super(elementToRename, editor, project, title, occurrences, elementToIntroduce);
}
@Override
public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames(getVariable().getInitializerGroovy(), new GroovyVariableValidator(context)));
public GrInplaceVariableIntroducer(String title,
OccurrencesChooser.ReplaceChoice replaceChoice,
GrIntroduceContext context) {
super(title, replaceChoice, context);
setAdvertisementText(getAdvertisementText());
}
@Nullable
private static String getAdvertisementText() {
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable");
if (shortcuts.length > 0) {
return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type";
}
return null;
}
@Override
protected String getActionName() {
return GrIntroduceVariableHandler.REFACTORING_NAME;
}
@Override
protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
return GroovyNameSuggestionUtil.suggestVariableNames(getContext().getExpression(), new GroovyVariableValidator(getContext()));
}
@Override
protected JComponent getComponent() {
myCanBeFinalCb = new NonFocusableCheckBox("Declare final");
@@ -91,22 +107,58 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer {
panel.setBorder(null);
if (myCanBeFinalCb != null) {
panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
new Insets(5, 5, 5, 5), 0, 0));
}
panel.add(Box.createVerticalBox(), new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0));
panel.add(Box.createVerticalBox(),
new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
return panel;
}
@Nullable
@Override
public void finish(boolean success) {
super.finish(success);
protected GroovyIntroduceVariableSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context,
@NotNull final OccurrencesChooser.ReplaceChoice choice,
final String[] names) {
return new GroovyIntroduceVariableSettings() {
private final CanonicalTypes.Type myType;
if (success) {
GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = getVariable().getDeclaredType() == null;
}
{
GrExpression expression = context.getExpression();
StringPartInfo stringPart = context.getStringPart();
GrVariable var = context.getVar();
PsiType type = expression != null ? expression.getType() :
var != null ? var.getType() :
stringPart != null ? stringPart.getLiteral().getType() :
null;
myType = type != null ? CanonicalTypes.createTypeWrapper(type) : null;
}
@Override
public boolean isDeclareFinal() {
return myCanBeFinalCb != null ? myCanBeFinalCb.isSelected() : false;
}
@Nullable
@Override
public String getName() {
return names[0];
}
@Override
public boolean replaceAllOccurrences() {
return choice == OccurrencesChooser.ReplaceChoice.ALL;
}
@Nullable
@Override
public PsiType getSelectedType() {
return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null;
}
};
}
@Override
@@ -119,4 +171,40 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer {
: PsiUtil.findModifierInList(variable.getModifierList(), GrModifier.DEF);
builder.replaceElement(element, "Variable_type", typeExpression, true, true);
}
}
protected GroovyIntroduceVariableSettings getSettings() {
return new GroovyIntroduceVariableSettings() {
@Override
public boolean isDeclareFinal() {
return myCanBeFinalCb.isSelected();
}
@Nullable
@Override
public String getName() {
return GrInplaceVariableIntroducer.this.getInputName();
}
@Override
public boolean replaceAllOccurrences() {
return isReplaceAllOccurrences();
}
@Nullable
@Override
public PsiType getSelectedType() {
return GrInplaceVariableIntroducer.this.getSelectedType();
}
};
}
@Override
protected void saveSettings(@NotNull GrVariable variable) {
GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = variable.getDeclaredType() == null;
}
@Override
protected int getCaretOffset() {
return getVariable().getNameIdentifierGroovy().getTextRange().getEndOffset();
}
}
@@ -46,26 +46,26 @@ import java.util.List;
/**
* @author Max Medvedev
*/
public class GrIntroduceLocalVariableProcessor {
public abstract class GrIntroduceLocalVariableProcessor {
private static final Logger LOG = Logger.getInstance(GrIntroduceLocalVariableProcessor.class);
private final GrIntroduceContext myContext;
private final GroovyIntroduceVariableSettings mySettings;
private final boolean myProcessUsages;
private final PsiElement[] myOccurrences;
private GrExpression myExpression;
private final GrIntroduceVariableHandler myHandler;
public GrIntroduceLocalVariableProcessor(@NotNull GrIntroduceContext context,
@NotNull GroovyIntroduceVariableSettings settings,
@NotNull PsiElement[] occurrences,
@NotNull GrExpression expression,
@NotNull GrIntroduceVariableHandler handler) {
boolean processUsages) {
myContext = context;
mySettings = settings;
myProcessUsages = processUsages;
myOccurrences = settings.replaceAllOccurrences() ? occurrences : new PsiElement[]{expression};
myExpression = expression;
myHandler = handler;
}
@NotNull
@@ -75,7 +75,7 @@ public class GrIntroduceLocalVariableProcessor {
preprocessOccurrences();
int expressionIndex = ArrayUtilRt.find(myOccurrences, myExpression);
final PsiElement[] replaced = processOccurrences();
final PsiElement[] replaced = myProcessUsages ? processOccurrences() : myOccurrences;
PsiElement replacedExpression = replaced[expressionIndex];
GrStatement anchor = getAnchor(replaced);
@@ -84,9 +84,7 @@ public class GrIntroduceLocalVariableProcessor {
return insertVariableDefinition(declaration, anchor, replacedExpression);
}
private void refreshPositionMarker(PsiElement e) {
myHandler.refreshPositionMarker(myContext.getEditor().getDocument().createRangeMarker(e.getTextRange()));
}
protected abstract void refreshPositionMarker(PsiElement e);
private static boolean isControlStatementBranch(GrStatement statement) {
return statement.getParent() instanceof GrLoopStatement && statement == ((GrLoopStatement)statement.getParent()).getBody() ||
@@ -13,24 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.refactoring.introduce.variable;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.util.Pass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiType;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.util.CanonicalTypes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
@@ -48,10 +40,8 @@ import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import java.util.List;
/**
* @author ilyas
* Created by Max Medvedev on 10/29/13
*/
public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyIntroduceVariableSettings, GrControlFlowOwner> {
public static final String DUMMY_NAME = "________________xxx_________________";
@@ -129,8 +119,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
public GrVariable runRefactoring(@NotNull final GrIntroduceContext context, @NotNull final GroovyIntroduceVariableSettings settings) {
// Generating variable declaration
final GrVariableDeclaration varDecl = generateDeclaration(context, settings);
GrVariable insertedVar = processExpression(context, settings, varDecl);
GrVariable insertedVar = processExpression(context, settings, true);
if (context.getEditor() != null && getPositionMarker() != null) {
context.getEditor().getCaretModel().moveToOffset(getPositionMarker().getEndOffset());
@@ -140,72 +129,11 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
}
@Override
protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrVariable var,
@NotNull GrIntroduceContext context,
@NotNull GroovyIntroduceVariableSettings settings,
@NotNull List<RangeMarker> occurrenceMarkers,
RangeMarker varRangeMarker, RangeMarker expressionRangeMarker,
RangeMarker stringPartRangeMarker) {
context.getEditor().getCaretModel().moveToOffset(var.getTextOffset());
GrInplaceVariableIntroducer introducer = new GrInplaceVariableIntroducer(var, context.getEditor(), context.getProject(), REFACTORING_NAME, occurrenceMarkers, var);
introducer.setAdvertisementText(getAdvertisementText(var.getDeclaredType() != null));
return introducer;
}
@Nullable
private static String getAdvertisementText(final boolean hasTypeSuggestion) {
final Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
if (hasTypeSuggestion) {
final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable");
if (shortcuts.length > 0) {
return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type";
}
}
return null;
}
@Override
protected GroovyIntroduceVariableSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) {
return new GroovyIntroduceVariableSettings() {
private final CanonicalTypes.Type myType;
private final String myName;
{
GrExpression expression = context.getExpression();
StringPartInfo stringPart = context.getStringPart();
GrVariable var = context.getVar();
PsiType type = expression != null ? expression.getType() :
var != null ? var.getType() :
stringPart != null ? stringPart.getLiteral().getType() :
null;
myType = type != null ?CanonicalTypes.createTypeWrapper(type) : null;
myName = new GrVariableNameSuggester(context, new GroovyVariableValidator(context)).suggestNames().iterator().next();
}
protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
return new GrInplaceVariableIntroducer(getRefactoringName(), choice, context) {
@Override
public boolean isDeclareFinal() {
return false;
}
@Nullable
@Override
public String getName() {
return myName;
}
@Override
public boolean replaceAllOccurrences() {
return choice == OccurrencesChooser.ReplaceChoice.ALL;
}
@Nullable
@Override
public PsiType getSelectedType() {
return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null;
protected GrVariable runRefactoring(GrIntroduceContext context, GroovyIntroduceVariableSettings settings, boolean processUsages) {
return processExpression(context, settings, processUsages);
}
};
}
@@ -231,24 +159,31 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
@NotNull
private GrVariable processExpression(@NotNull GrIntroduceContext context,
@NotNull GroovyIntroduceVariableSettings settings,
@NotNull GrVariableDeclaration varDecl) {
boolean processUsages) {
GrVariableDeclaration varDecl = generateDeclaration(context, settings);
if (context.getStringPart() != null) {
final GrExpression ref = processLiteral(DUMMY_NAME, context.getStringPart(), context.getProject());
return doProcessExpression(context, settings, varDecl, new PsiElement[]{ref}, ref);
return doProcessExpression(context, settings, varDecl, new PsiElement[]{ref}, ref, processUsages);
}
else {
final GrExpression expression = context.getExpression();
assert expression != null;
return doProcessExpression(context, settings, varDecl, context.getOccurrences(), expression);
return doProcessExpression(context, settings, varDecl, context.getOccurrences(), expression, processUsages);
}
}
private GrVariable doProcessExpression(@NotNull GrIntroduceContext context,
private GrVariable doProcessExpression(@NotNull final GrIntroduceContext context,
@NotNull GroovyIntroduceVariableSettings settings,
@NotNull GrVariableDeclaration varDecl,
@NotNull PsiElement[] elements,
@NotNull GrExpression expression) {
return new GrIntroduceLocalVariableProcessor(context, settings, elements, expression, this).processExpression(varDecl);
@NotNull GrExpression expression, boolean processUsages) {
return new GrIntroduceLocalVariableProcessor(context, settings, elements, expression, processUsages) {
@Override
protected void refreshPositionMarker(PsiElement e) {
GrIntroduceVariableHandler.this.refreshPositionMarker(context.getEditor().getDocument().createRangeMarker(e.getTextRange()));
}
}.processExpression(varDecl);
}
@NotNull
+2
View File
@@ -22,6 +22,8 @@
serviceImplementation="org.zmlx.hg4idea.HgRootsHandler" />
<projectService serviceInterface="org.zmlx.hg4idea.HgRememberedInputs"
serviceImplementation="org.zmlx.hg4idea.HgRememberedInputs"/>
<projectService serviceImplementation="org.zmlx.hg4idea.log.HgContentRevisionFactory"/>
</extensions>
<project-components>
@@ -0,0 +1,58 @@
/*
* 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 org.zmlx.hg4idea.log;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.ContentRevisionFactory;
import com.intellij.vcs.log.Hash;
import org.jetbrains.annotations.NotNull;
import org.zmlx.hg4idea.HgContentRevision;
import org.zmlx.hg4idea.HgFile;
import org.zmlx.hg4idea.HgRevisionNumber;
import java.io.File;
/**
*
*/
public class HgContentRevisionFactory extends ContentRevisionFactory {
@NotNull private final Project myProject;
@SuppressWarnings("UnusedDeclaration")
private HgContentRevisionFactory(@NotNull Project project) {
myProject = project;
}
public static HgContentRevisionFactory getInstance(Project project) {
return ServiceManager.getService(project, HgContentRevisionFactory.class);
}
@NotNull
@Override
public ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash) {
return new HgContentRevision(myProject, new HgFile(myProject, file), HgRevisionNumber.getInstance("", hash.asString()));
}
@NotNull
@Override
public ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash) {
return new HgContentRevision(myProject, new HgFile(root, new File(path)), HgRevisionNumber.getInstance("", hash.asString()));
}
}
@@ -33,6 +33,7 @@ import org.zmlx.hg4idea.*;
import org.zmlx.hg4idea.action.HgCommandResultNotifier;
import org.zmlx.hg4idea.command.HgLogCommand;
import org.zmlx.hg4idea.execution.HgCommandException;
import org.zmlx.hg4idea.log.HgContentRevisionFactory;
import org.zmlx.hg4idea.provider.HgCommittedChangeList;
import java.io.File;
@@ -61,7 +62,7 @@ public class HgHistoryUtil {
return ContainerUtil.mapNotNull(result, new Function<HgCommittedChangeList, VcsFullCommitDetails>() {
@Override
public VcsFullCommitDetails fun(HgCommittedChangeList record) {
return createCommit(root, record);
return createCommit(project, root, record);
}
});
}
@@ -169,7 +170,7 @@ public class HgHistoryUtil {
}
@NotNull
private static VcsFullCommitDetails createCommit(@NotNull VirtualFile root,
private static VcsFullCommitDetails createCommit(@NotNull Project project, @NotNull VirtualFile root,
@NotNull HgCommittedChangeList record) {
final VcsLogObjectsFactory factory = ServiceManager.getService(VcsLogObjectsFactory.class);
@@ -185,7 +186,7 @@ public class HgHistoryUtil {
revNumber.getSubject(),
revNumber.getAuthor(), "", revNumber.getCommitMessage(), record.getCommitterName(),
"", record.getCommitDate().getTime(),
ContainerUtil.newArrayList(record.getChanges()));
ContainerUtil.newArrayList(record.getChanges()), HgContentRevisionFactory.getInstance(project));
}
@Nullable
@@ -224,10 +224,10 @@ SIMPLE_VALUE_RE = re.compile(
########################### parsing ###########################################################
if version[0] < 3:
from pyparsing import *
from pycharm_generator_utils.pyparsing import *
else:
#noinspection PyUnresolvedReferences
from pyparsing_py3 import *
from pycharm_generator_utils.pyparsing_py3 import *
# grammar to parse parameter lists
@@ -169,10 +169,12 @@ public class PyNames {
"__all__",
"__author__",
"__bases__",
"__defaults__",
"__dict__",
"__doc__",
"__docformat__",
"__file__",
"__kwdefaults__",
"__members__",
"__metaclass__",
"__mod__",
@@ -304,6 +306,7 @@ public class PyNames {
.put("__rdivmod__", _self_other_descr)
.put("__reduce__", _only_self_descr)
.put("__repr__", _only_self_descr)
.put("__reversed__", _only_self_descr)
.put("__rfloordiv__", _self_other_descr)
.put("__rlshift__", _self_other_descr)
.put("__rmod__", _self_other_descr)
@@ -338,6 +341,9 @@ public class PyNames {
public static ImmutableMap<String, BuiltinDescription> PY3_BUILTIN_METHODS = ImmutableMap.<String, BuiltinDescription>builder()
.putAll(BuiltinMethods)
.put("__bool__", _only_self_descr)
.put("__bytes__", _only_self_descr)
.put("__format__", new BuiltinDescription("(self, format_spec)"))
.put("__round__", new BuiltinDescription("(self, n=None)"))
.build();
public static ImmutableMap<String, BuiltinDescription> getBuiltinMethods(LanguageLevel level) {
@@ -17,15 +17,21 @@ package com.jetbrains.python.projectView;
import com.intellij.ide.projectView.SelectableTreeStructureProvider;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.NamedLibraryElementNode;
import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.roots.JdkOrderEntry;
import com.intellij.openapi.roots.LibraryOrSdkOrderEntry;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.psi.PyDocStringOwner;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.sdk.PythonSdkType;
import java.util.ArrayList;
import java.util.Collection;
@@ -37,6 +43,9 @@ import java.util.List;
public class PyTreeStructureProvider implements SelectableTreeStructureProvider, DumbAware {
@Override
public Collection<AbstractTreeNode> modify(AbstractTreeNode parent, Collection<AbstractTreeNode> children, ViewSettings settings) {
if (parent instanceof NamedLibraryElementNode) {
return hideSkeletons((NamedLibraryElementNode)parent, children);
}
if (settings.isShowMembers()) {
List<AbstractTreeNode> newChildren = new ArrayList<AbstractTreeNode>();
for (AbstractTreeNode child : children) {
@@ -52,6 +61,25 @@ public class PyTreeStructureProvider implements SelectableTreeStructureProvider,
return children;
}
protected Collection<AbstractTreeNode> hideSkeletons(NamedLibraryElementNode parent, Collection<AbstractTreeNode> children) {
LibraryOrSdkOrderEntry orderEntry = parent.getValue().getOrderEntry();
if (orderEntry instanceof JdkOrderEntry) {
List<AbstractTreeNode> newChildren = new ArrayList<AbstractTreeNode>();
for (AbstractTreeNode child : children) {
if (child instanceof PsiDirectoryNode) {
PsiDirectory directory = ((PsiDirectoryNode)child).getValue();
PsiDirectory dirParent = directory.getParent();
if (dirParent != null && dirParent.getName().equals(PythonSdkType.SKELETON_DIR_NAME)) {
continue;
}
}
newChildren.add(child);
}
return newChildren;
}
return children;
}
@Override
public Object getData(Collection<AbstractTreeNode> selected, String dataName) {
return null;
@@ -17,9 +17,9 @@ package com.jetbrains.python.sdk.flavors;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -67,7 +67,7 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor {
public static VirtualFile getDefaultLocation() {
final String path = System.getenv().get("WORKON_HOME");
if (!StringUtil.isEmpty(path)) {
return LocalFileSystem.getInstance().findFileByPath(path.replace('\\','/'));
return LocalFileSystem.getInstance().findFileByPath(FileUtil.expandUserHome(path).replace('\\','/'));
}
final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\','/'));
@@ -0,0 +1,2 @@
print(dict.fromkeys(<warning descr="Parameter 'seq' unfilled">)</warning>)
print(dict.fromkeys(['foo', 'bar']))
@@ -0,0 +1,5 @@
print(unicode())
print(unicode(''))
print(unicode('', 'utf-8'))
print(unicode('', 'utf-8', 'ignore'))
print(unicode('', 'utf-8', 'ignore', <warning descr="Unexpected argument">foo</warning>))
@@ -158,4 +158,14 @@ public class PyArgumentListInspectionTest extends PyTestCase {
public void testPropertyReturnsCallable() {
doTest();
}
// PY-11162
public void testUnicodeConstructor() {
doTest();
}
// PY-11169
public void testDictFromKeys() {
doTest();
}
}