Merge branch 'master' of git.labs.intellij.net:idea/community

Merge commit 'c667235951b68017e427bc7a9d9f6dd2b60a9d35' into HEAD
This commit is contained in:
irengrig
2010-10-06 01:47:44 +04:00
85 changed files with 1466 additions and 793 deletions
@@ -27,9 +27,8 @@ public class SuspendManagerUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.SuspendManagerUtil");
public static boolean isEvaluating(SuspendManager suspendManager, ThreadReferenceProxyImpl thread) {
for (Iterator<SuspendContextImpl> iterator = ((SuspendManagerImpl) suspendManager).getEventContexts().iterator(); iterator.hasNext();) {
SuspendContextImpl suspendContext = iterator.next();
if(suspendContext.isEvaluating() && thread.equals(suspendContext.getThread())) {
for (SuspendContextImpl suspendContext : suspendManager.getEventContexts()) {
if (suspendContext.isEvaluating() && thread.equals(suspendContext.getThread())) {
return true;
}
}
@@ -121,8 +120,8 @@ public class SuspendManagerUtil {
}
public static SuspendContextImpl getEvaluatingContext(SuspendManager suspendManager, ThreadReferenceProxyImpl thread) {
for (SuspendContextImpl suspendContext : ((SuspendManagerImpl)suspendManager).getEventContexts()) {
if (suspendContext.isEvaluating() && suspendContext.getThread() == thread) {
for (SuspendContextImpl suspendContext : suspendManager.getEventContexts()) {
if (!suspendContext.isResumed() && suspendContext.isEvaluating() && suspendContext.getThread() == thread) {
return suspendContext;
}
}
@@ -154,7 +154,8 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
return getStackFrame().location();
}
catch (InvalidStackFrameException e) {
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.thread.resumed"), e);
clearCaches();
return location();
}
}
@@ -98,6 +98,7 @@ public class CreateNewLibraryAction extends AnAction {
private void appendLibraryToModules(final ModuleStructureConfigurable rootConfigurable, final Library libraryToSelect) {
final List<Module> modules = new ArrayList<Module>();
ContainerUtil.addAll(modules, rootConfigurable.getModules());
if (modules.isEmpty()) return;
final ChooseModulesDialog dlg = new ChooseModulesDialog(myProject,
modules, ProjectBundle.message("choose.modules.dialog.title"),
ProjectBundle
@@ -219,7 +219,7 @@ public class CodeInsightUtil {
public static boolean areExpressionsEquivalent(PsiExpression expr1, PsiExpression expr2) {
return PsiEquivalenceUtil.areElementsEquivalent(expr1, expr2, new Comparator<PsiElement>() {
public int compare(PsiElement o1, PsiElement o2) {
if (o1 instanceof PsiParameter && o2 instanceof PsiParameter) {
if (o1 instanceof PsiParameter && o2 instanceof PsiParameter && ((PsiParameter)o1).getDeclarationScope() instanceof PsiMethod) {
return ((PsiParameter)o1).getName().compareTo(((PsiParameter)o2).getName());
}
return 1;
@@ -238,6 +238,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction {
}
int ei = 0;
int pi = 0;
PsiParameter varargParam = targetMethod.isVarArgs() ? parameters[parameters.length - 1] : null;
while (ei < expressions.length || pi < parameters.length) {
PsiExpression expression = ei < expressions.length ? expressions[ei] : null;
PsiParameter parameter = pi < parameters.length ? parameters[pi] : null;
@@ -248,7 +249,16 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction {
pi++;
ei++;
}
else if (isArgumentInVarargPosition(expressions, ei, varargParam, substitutor)) {
if (pi == parameters.length - 1) {
assert varargParam != null;
result.add(new ParameterInfoImpl(pi, varargParam.getName(), varargParam.getType()));
}
pi++;
ei++;
}
else if (expression != null) {
if (varargParam != null && pi >= parameters.length) return null;
PsiType exprType = RefactoringUtil.getTypeByExpression(expression);
if (exprType == null) return null;
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(expression.getProject());
@@ -257,7 +267,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction {
ei++;
}
}
if (result.size() != expressions.length) return null;
if (result.size() != expressions.length && varargParam == null) return null;
}
else {
//parameter type changed
@@ -291,6 +301,17 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction {
return result.toArray(new ParameterInfoImpl[result.size()]);
}
private static boolean isArgumentInVarargPosition(PsiExpression[] expressions, int ei, PsiParameter varargParam, PsiSubstitutor substitutor) {
if (varargParam == null) return false;
final PsiExpression expression = expressions[ei];
if (expression == null || TypeConversionUtil.areTypesAssignmentCompatible(substitutor.substitute(((PsiEllipsisType)varargParam.getType()).getComponentType()), expression)) {
final int lastExprIdx = expressions.length - 1;
if (ei == lastExprIdx) return true;
return expressions[lastExprIdx].getType() != PsiType.NULL;
}
return false;
}
private static String suggestUniqueParameterName(JavaCodeStyleManager codeStyleManager,
PsiExpression expression,
PsiType exprType,
@@ -40,14 +40,16 @@ import org.jetbrains.annotations.NotNull;
* @author max
*/
public class JavaParserDefinition implements ParserDefinition {
public static final boolean USE_NEW_PARSER = false;
@NotNull
public Lexer createLexer(Project project) {
return new JavaLexer(LanguageLevelProjectExtension.getInstance(project).getLanguageLevel());
public Lexer createLexer(final Project project) {
final LanguageLevel languageLevel = LanguageLevelProjectExtension.getInstance(project).getLanguageLevel();
return createLexer(languageLevel);
}
@NotNull
public static Lexer createLexer(LanguageLevel languageLevel) {
public static Lexer createLexer(final LanguageLevel languageLevel) {
return new JavaLexer(languageLevel);
}
@@ -72,11 +74,11 @@ public class JavaParserDefinition implements ParserDefinition {
@NotNull
public PsiParser createParser(final Project project) {
return PsiUtil.NULL_PARSER;
throw new UnsupportedOperationException("Should not be called directly");
}
@NotNull
public PsiElement createElement(ASTNode node) {
public PsiElement createElement(final ASTNode node) {
final IElementType type = node.getElementType();
if (type instanceof JavaStubElementType) {
return ((JavaStubElementType)type).createPsi(node);
@@ -85,7 +87,7 @@ public class JavaParserDefinition implements ParserDefinition {
return PsiUtil.NULL_PSI_ELEMENT;
}
public PsiFile createFile(FileViewProvider viewProvider) {
public PsiFile createFile(final FileViewProvider viewProvider) {
return new PsiJavaFileImpl(viewProvider);
}
@@ -172,7 +172,6 @@ public class JavaParserUtil {
return builder;
}
@NotNull
public static ASTNode parseFragment(final ASTNode chameleon, final ParserWrapper wrapper) {
final PsiElement psi = (chameleon.getTreeParent() != null ? chameleon.getTreeParent().getPsi() : chameleon.getPsi());
assert psi != null : chameleon;
@@ -22,30 +22,31 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.impl.source.JavaFileElementType;
import com.intellij.psi.tree.IStubFileElementType;
public class JavaStubElementTypes {
public static final JavaClassElementType CLASS = new JavaClassElementType("CLASS");
public static final JavaClassElementType ANONYMOUS_CLASS = new JavaClassElementType("ANONYMOUS_CLASS");
public static final JavaClassElementType ENUM_CONSTANT_INITIALIZER = new JavaClassElementType("ENUM_CONSTANT_INITIALIZER");
public interface JavaStubElementTypes {
JavaClassElementType CLASS = new JavaClassElementType("CLASS");
JavaClassElementType ANONYMOUS_CLASS = new JavaClassElementType("ANONYMOUS_CLASS");
JavaClassElementType ENUM_CONSTANT_INITIALIZER = new JavaClassElementType("ENUM_CONSTANT_INITIALIZER");
public static final JavaModifierListElementType MODIFIER_LIST = new JavaModifierListElementType();
public static final JavaMethodElementType METHOD = new JavaMethodElementType("METHOD");
public static final JavaMethodElementType ANNOTATION_METHOD = new JavaMethodElementType("ANNOTATION_METHOD");
public static final JavaFieldStubElementType FIELD = new JavaFieldStubElementType("FIELD");
public static final JavaFieldStubElementType ENUM_CONSTANT = new JavaFieldStubElementType("ENUM_CONSTANT");
JavaModifierListElementType MODIFIER_LIST = new JavaModifierListElementType();
JavaMethodElementType METHOD = new JavaMethodElementType("METHOD");
JavaMethodElementType ANNOTATION_METHOD = new JavaMethodElementType("ANNOTATION_METHOD");
JavaFieldStubElementType FIELD = new JavaFieldStubElementType("FIELD");
JavaFieldStubElementType ENUM_CONSTANT = new JavaFieldStubElementType("ENUM_CONSTANT");
public static final JavaAnnotationElementType ANNOTATION = new JavaAnnotationElementType();
public static final JavaClassReferenceListElementType EXTENDS_LIST = new JavaClassReferenceListElementType("EXTENDS_LIST");
public static final JavaClassReferenceListElementType IMPLEMENTS_LIST = new JavaClassReferenceListElementType("IMPLEMENTS_LIST");
public static final JavaClassReferenceListElementType THROWS_LIST = new JavaClassReferenceListElementType("THROWS_LIST");
public static final JavaClassReferenceListElementType EXTENDS_BOUND_LIST = new JavaClassReferenceListElementType("EXTENDS_BOUND_LIST");
JavaAnnotationElementType ANNOTATION = new JavaAnnotationElementType();
JavaClassReferenceListElementType EXTENDS_LIST = new JavaClassReferenceListElementType("EXTENDS_LIST");
JavaClassReferenceListElementType IMPLEMENTS_LIST = new JavaClassReferenceListElementType("IMPLEMENTS_LIST");
JavaClassReferenceListElementType THROWS_LIST = new JavaClassReferenceListElementType("THROWS_LIST");
JavaClassReferenceListElementType EXTENDS_BOUND_LIST = new JavaClassReferenceListElementType("EXTENDS_BOUND_LIST");
public static final JavaParameterElementType PARAMETER = new JavaParameterElementType();
public static final JavaParameterListElementType PARAMETER_LIST = new JavaParameterListElementType();
public static final JavaTypeParameterElementType TYPE_PARAMETER = new JavaTypeParameterElementType();
public static final JavaTypeParameterListElementType TYPE_PARAMETER_LIST = new JavaTypeParameterListElementType();
public static final JavaClassInitializerElementType CLASS_INITIALIZER = new JavaClassInitializerElementType();
public static final JavaImportListElementType IMPORT_LIST = new JavaImportListElementType();
public static final JavaImportStatementElementType IMPORT_STATEMENT = new JavaImportStatementElementType("IMPORT_STATEMENT");
public static final JavaImportStatementElementType IMPORT_STATIC_STATEMENT = new JavaImportStatementElementType("IMPORT_STATIC_STATEMENT");
public static final IStubFileElementType JAVA_FILE = new JavaFileElementType();
JavaParameterElementType PARAMETER = new JavaParameterElementType();
JavaParameterListElementType PARAMETER_LIST = new JavaParameterListElementType();
JavaTypeParameterElementType TYPE_PARAMETER = new JavaTypeParameterElementType();
JavaTypeParameterListElementType TYPE_PARAMETER_LIST = new JavaTypeParameterListElementType();
JavaClassInitializerElementType CLASS_INITIALIZER = new JavaClassInitializerElementType();
JavaImportListElementType IMPORT_LIST = new JavaImportListElementType();
JavaImportStatementElementType IMPORT_STATEMENT = new JavaImportStatementElementType("IMPORT_STATEMENT");
JavaImportStatementElementType IMPORT_STATIC_STATEMENT = new JavaImportStatementElementType("IMPORT_STATIC_STATEMENT");
IStubFileElementType JAVA_FILE = new JavaFileElementType();
}
@@ -34,7 +34,7 @@ import java.io.IOException;
public class JavaTypeParameterElementType extends JavaStubElementType<PsiTypeParameterStub, PsiTypeParameter> {
public JavaTypeParameterElementType() {
super("TYPE_PARAMETR");
super("TYPE_PARAMETER");
}
public PsiTypeParameter createPsi(final PsiTypeParameterStub stub) {
@@ -20,7 +20,11 @@
package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.java.JavaParserDefinition;
import com.intellij.lang.java.parser.FileParser;
import com.intellij.lang.java.parser.JavaParserUtil;
import com.intellij.lexer.JavaLexer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
@@ -41,7 +45,7 @@ import com.intellij.util.io.StringRef;
import java.io.IOException;
public class JavaFileElementType extends IStubFileElementType<PsiJavaFileStub> {
public static final int STUB_VERSION = 3;
public static final int STUB_VERSION = JavaParserDefinition.USE_NEW_PARSER ? 4 : 3;
public JavaFileElementType() {
super("java.FILE", StdLanguages.JAVA);
@@ -61,7 +65,17 @@ public class JavaFileElementType extends IStubFileElementType<PsiJavaFileStub> {
return dir == null || dir.getUserData(LanguageLevel.KEY) != null;
}
public ASTNode parseContents(ASTNode chameleon) {
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon);
final PsiBuilder.Marker root = builder.mark();
FileParser.parse(builder);
root.done(this);
return builder.getTreeBuilt().getFirstChildNode();
}
FileElement node = (FileElement)chameleon;
final CharSequence seq = node.getChars();
@@ -15,8 +15,12 @@
*/
package com.intellij.psi.impl.source.tree;
import com.intellij.lang.ASTNode;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.*;
import com.intellij.lang.java.JavaParserDefinition;
import com.intellij.lang.java.parser.ExpressionParser;
import com.intellij.lang.java.parser.JavaParserUtil;
import com.intellij.lang.java.parser.ReferenceParser;
import com.intellij.lang.java.parser.StatementParser;
import com.intellij.lexer.JavaLexer;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.project.Project;
@@ -31,12 +35,13 @@ import com.intellij.psi.text.BlockSupport;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IErrorCounterReparseableElementType;
import com.intellij.psi.tree.ILazyParseableElementType;
import com.intellij.psi.tree.ILightLazyParseableElementType;
import com.intellij.psi.tree.java.IJavaElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.CharTable;
import com.intellij.util.diff.FlyweightCapableTreeStructure;
public interface JavaElementType {
IElementType CLASS = JavaStubElementTypes.CLASS;
IElementType ANONYMOUS_CLASS = JavaStubElementTypes.ANONYMOUS_CLASS;
IElementType ENUM_CONSTANT_INITIALIZER = JavaStubElementTypes.ENUM_CONSTANT_INITIALIZER;
@@ -120,13 +125,24 @@ public interface JavaElementType {
IElementType ANNOTATION_PARAMETER_LIST = new IJavaElementType("ANNOTATION_PARAMETER_LIST", true);
IElementType METHOD_RECEIVER = new IJavaElementType("METHOD_RECEIVER");
ILazyParseableElementType CODE_BLOCK = new IErrorCounterReparseableElementType("CODE_BLOCK", StdLanguages.JAVA) {
class ICodeBlockElementType extends IErrorCounterReparseableElementType {
private ICodeBlockElementType() {
super("CODE_BLOCK", StdLanguages.JAVA);
}
@Override
public ASTNode createNode(CharSequence text) {
public ASTNode createNode(final CharSequence text) {
return new PsiCodeBlockImpl(text);
}
public ASTNode parseContents(ASTNode chameleon) {
@Override
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon);
StatementParser.parseCodeBlockDeep(builder, true);
return builder.getTreeBuilt().getFirstChildNode();
}
final CharSequence seq = chameleon.getChars();
ASTNode original = chameleon.getUserData(BlockSupport.TREE_TO_BE_REPARSED);
@@ -137,20 +153,20 @@ public interface JavaElementType {
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(TreeUtil.getFileElement((TreeElement)context).getPsi());
JavaParsingContext parsingContext = new JavaParsingContext(table, languageLevel);
return parsingContext.getStatementParsing().parseCodeBlockText(manager, new JavaLexer(languageLevel),
seq, 0, seq.length(), 0).getFirstChildNode();
seq, 0, seq.length(), 0).getFirstChildNode();
}
public int getErrorsCount(CharSequence seq, Project project) {
public int getErrorsCount(final CharSequence seq, final Project project) {
final Lexer lexer = new JavaLexer(LanguageLevel.HIGHEST);
lexer.start(seq);
if(lexer.getTokenType() != JavaTokenType.LBRACE) return FATAL_ERROR;
if (lexer.getTokenType() != JavaTokenType.LBRACE) return FATAL_ERROR;
lexer.advance();
int balance = 1;
while(true){
while (true) {
IElementType type = lexer.getTokenType();
if (type == null) break;
if(balance == 0) return FATAL_ERROR;
if (balance == 0) return FATAL_ERROR;
if (type == JavaTokenType.LBRACE) {
balance++;
}
@@ -161,11 +177,29 @@ public interface JavaElementType {
}
return balance;
}
};
}
class ICodeBlockNewElementType extends ICodeBlockElementType implements ILightLazyParseableElementType {
public FlyweightCapableTreeStructure<LighterASTNode> parseContents(final LighterLazyParseableNode chameleon) {
final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon);
StatementParser.parseCodeBlockDeep(builder, true);
return builder.getLightTree();
}
}
ILazyParseableElementType CODE_BLOCK = JavaParserDefinition.USE_NEW_PARSER ? new ICodeBlockNewElementType() : new ICodeBlockElementType();
IElementType STATEMENTS = new ICodeFragmentElementType("STATEMENTS", StdLanguages.JAVA) {
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
new JavaParserUtil.ParserWrapper() {
public void parse(final PsiBuilder builder) {
StatementParser.parseStatements(builder);
}
});
}
//The following are the children of code fragment
IElementType STATEMENTS = new ICodeFragmentElementType("STATEMENTS", StdLanguages.JAVA){
public ASTNode parseContents(ASTNode chameleon) {
final CharSequence chars = chameleon.getChars();
final PsiManager manager = ((FileElement)chameleon).getManager();
final CharTable table = SharedImplUtil.findCharTableByTree(chameleon);
@@ -174,8 +208,17 @@ public interface JavaElementType {
}
};
IElementType EXPRESSION_TEXT = new ICodeFragmentElementType("EXPRESSION_TEXT", StdLanguages.JAVA){
public ASTNode parseContents(ASTNode chameleon) {
IElementType EXPRESSION_TEXT = new ICodeFragmentElementType("EXPRESSION_TEXT", StdLanguages.JAVA) {
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
new JavaParserUtil.ParserWrapper() {
public void parse(final PsiBuilder builder) {
ExpressionParser.parse(builder);
}
});
}
final CharSequence chars = chameleon.getChars();
final PsiManager manager = ((FileElement)chameleon).getManager();
final JavaParsingContext context = new JavaParsingContext(SharedImplUtil.findCharTableByTree(chameleon), LanguageLevel.HIGHEST);
@@ -183,17 +226,37 @@ public interface JavaElementType {
}
};
IElementType REFERENCE_TEXT = new ICodeFragmentElementType("REFERENCE_TEXT", StdLanguages.JAVA){
public ASTNode parseContents(ASTNode chameleon) {
IElementType REFERENCE_TEXT = new ICodeFragmentElementType("REFERENCE_TEXT", StdLanguages.JAVA) {
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
new JavaParserUtil.ParserWrapper() {
public void parse(final PsiBuilder builder) {
ReferenceParser.parseJavaCodeReference(builder, false, true, false, false);
}
});
}
final CharSequence chars = chameleon.getChars();
return Parsing.parseJavaCodeReferenceText(((FileElement)chameleon).getManager(), chars, 0, chars.length(), SharedImplUtil.findCharTableByTree(chameleon), true);
return Parsing.parseJavaCodeReferenceText(((FileElement)chameleon).getManager(), chars, 0, chars.length(),
SharedImplUtil.findCharTableByTree(chameleon), true);
}
};
IElementType TYPE_TEXT = new ICodeFragmentElementType("TYPE_TEXT", StdLanguages.JAVA){
public ASTNode parseContents(ASTNode chameleon) {
IElementType TYPE_TEXT = new ICodeFragmentElementType("TYPE_TEXT", StdLanguages.JAVA) {
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
new JavaParserUtil.ParserWrapper() {
public void parse(final PsiBuilder builder) {
ReferenceParser.parseType(builder);
}
});
}
final CharSequence chars = chameleon.getChars();
return Parsing.parseTypeText(((FileElement)chameleon).getManager(), null, chars, 0, chars.length(), 0, SharedImplUtil.findCharTableByTree(chameleon));
return Parsing.parseTypeText(((FileElement)chameleon).getManager(), null, chars, 0, chars.length(), 0,
SharedImplUtil.findCharTableByTree(chameleon));
}
};
}
@@ -411,7 +411,7 @@ class JavaChangeInfoImpl implements JavaChangeInfo {
if (!newName.equals(that.newName)) return false;
if (newNameIdentifier != null ? !newNameIdentifier.equals(that.newNameIdentifier) : that.newNameIdentifier != null) return false;
if (!Arrays.equals(newParms, that.newParms)) return false;
if (newReturnType != null ? !Comparing.strEqual(newReturnType.getTypeText(), that.newReturnType.getTypeText()) : that.newReturnType != null) return false;
if (newReturnType != null ? that.newReturnType == null || !Comparing.strEqual(newReturnType.getTypeText(), that.newReturnType.getTypeText()) : that.newReturnType != null) return false;
if (newVisibility != null ? !newVisibility.equals(that.newVisibility) : that.newVisibility != null) return false;
if (!oldName.equals(that.oldName)) return false;
if (!Arrays.equals(oldParameterNames, that.oldParameterNames)) return false;
@@ -124,6 +124,7 @@ class IntroduceConstantDialog extends DialogWrapper {
myVPanel.setVisibility(JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY);
myIntroduceEnumConstantCb.setEnabled(EnumConstantsUtil.isSuitableForEnumConstant(getSelectedType(), myTargetClass));
updateVisibilityPanel();
updateButtons();
}
public String getEnteredName() {
@@ -172,7 +173,11 @@ class IntroduceConstantDialog extends DialogWrapper {
myNameField = new NameSuggestionsField(myProject);
myNameSuggestionPanel.setLayout(new BorderLayout());
myNameField.addDataChangedListener(new NameSuggestionsField.DataChanged() {
public void dataChanged() {
updateButtons();
}
});
myNameSuggestionPanel.add(myNameField.getComponent(), BorderLayout.CENTER);
myNameSuggestionLabel.setLabelFor(myNameField.getFocusableComponent());
@@ -280,6 +285,10 @@ class IntroduceConstantDialog extends DialogWrapper {
return myPanel;
}
private void updateButtons() {
setOKActionEnabled(JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(getEnteredName()));
}
private void targetClassChanged() {
final String targetClassName = getTargetClassName();
myTargetClass = JavaPsiFacade.getInstance(myProject).findClass(targetClassName, GlobalSearchScope.projectScope(myProject));
@@ -30,7 +30,6 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringBundle;
import static com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler.InitializationPlace.*;
import com.intellij.refactoring.ui.*;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.RefactoringMessageUtil;
@@ -43,6 +42,8 @@ import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import static com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler.InitializationPlace.*;
class IntroduceFieldDialog extends DialogWrapper {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceField.IntroduceFieldDialog");
@@ -103,7 +104,7 @@ class IntroduceFieldDialog extends DialogWrapper {
init();
initializeControls(initializerExpression);
updateButtons();
}
private void initializeControls(PsiExpression initializerExpression) {
@@ -270,6 +271,11 @@ class IntroduceFieldDialog extends DialogWrapper {
gbConstraints.gridy = 1;
myNameField = new NameSuggestionsField(myProject);
panel.add(myNameField.getComponent(), gbConstraints);
myNameField.addDataChangedListener(new NameSuggestionsField.DataChanged() {
public void dataChanged() {
updateButtons();
}
});
namePrompt.setLabelFor(myNameField.getFocusableComponent());
myNameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField, createGenerator());
@@ -278,6 +284,10 @@ class IntroduceFieldDialog extends DialogWrapper {
return panel;
}
private void updateButtons() {
setOKActionEnabled(JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(getEnteredName()));
}
private String getTypeLabel() {
return myWillBeDeclaredStatic ?
RefactoringBundle.message("introduce.field.static.field.of.type") :
@@ -17,6 +17,7 @@ package com.intellij.refactoring.rename;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.pom.PomTarget;
import com.intellij.pom.PomTargetPsiElement;
import com.intellij.pom.references.PomService;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiTarget;
@@ -30,14 +31,14 @@ public class RenameAliasingPomTargetProcessor extends RenamePsiElementProcessor
@Override
public boolean canProcessElement(@Nullable PsiElement element) {
return element instanceof PomTarget;
return element instanceof PomTargetPsiElement;
}
@Override
public void prepareRenaming(PsiElement element, String newName, Map<PsiElement, String> allRenames) {
if (element instanceof PsiTarget) {
if (element instanceof PomTargetPsiElement) {
for (AliasingPsiTargetMapper mapper : Extensions.getExtensions(AliasingPsiTargetMapper.EP_NAME)) {
for (AliasingPsiTarget psiTarget : mapper.getTargets((PsiTarget)element)) {
for (AliasingPsiTarget psiTarget : mapper.getTargets(((PomTargetPsiElement)element).getTarget())) {
allRenames.put(PomService.convertToPsi(psiTarget), psiTarget.getNameAlias(newName));
}
}
@@ -0,0 +1,6 @@
// "Change signature of 'f(int...)' to 'f(String, int...)'" "true"
public class S {
void f(String s, int... args) {
f("",1,1);
}
}
@@ -0,0 +1,6 @@
// "Change signature of 'f(int...)' to 'f(String, int...)'" "true"
public class S {
void f(String s, int... args) {
f("",null);
}
}
@@ -0,0 +1,6 @@
// "Change signature of 'f(int...)' to 'f(String, int...)'" "true"
public class S {
void f(int... args) {
f("",1,1)<caret>;
}
}
@@ -0,0 +1,6 @@
// "Change signature of 'f(int...)' to 'f(String, int...)'" "true"
public class S {
void f(int... args) {
f("",null)<caret>;
}
}
@@ -0,0 +1,6 @@
// "Change signature of 'f(int...)' to 'f(int..., String)'" "false"
public class S {
void f(int... args) {
f(1,1, "")<caret>;
}
}
@@ -0,0 +1,12 @@
class A {
{
List<Integer> l = new ArrayList<Integer>();
for (Integer i : l) {
final String tostr = i.toString();
System.out.println(tostr);
}
for (Integer i : l) {
System.out.println(i.toString());
}
}
}
@@ -0,0 +1,11 @@
class A {
{
List<Integer> l = new ArrayList<Integer>();
for (Integer i : l) {
System.out.println(<selection>i.toString()</selection>);
}
for (Integer i : l) {
System.out.println(i.toString());
}
}
}
@@ -18,6 +18,7 @@ package com.intellij.lang.java.parser;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.java.JavaParserDefinition;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
@@ -120,7 +121,9 @@ public abstract class JavaParsingTestCase extends ParsingTestCase {
@Override
protected void doTest(final boolean checkResult) {
doTestDefaultParser(checkResult);
doTestNewParser();
if (JavaParserDefinition.USE_NEW_PARSER) {
doTestNewParser();
}
}
protected void doTestDefaultParser(final boolean checkResult) {
@@ -218,6 +218,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
doTest(new MockIntroduceVariableHandler("foo1", true, true, false, "Foo"));
}
public void testDifferentForeachParameters () throws Exception {
doTest(new MockIntroduceVariableHandler("tostr", true, true, false, "java.lang.String"));
}
public void testSiblingInnerClassType() throws Exception {
doTest(new MockIntroduceVariableHandler("vari", true, false, false, "A.B"){
@Override
@@ -57,7 +57,7 @@ public interface PsiJavaFile extends PsiImportHolder, PsiClassOwner {
@NotNull PsiElement[] getOnDemandImports(boolean includeImplicit, @Deprecated boolean checkIncludes);
/**
* Returns the list of classs which have been imported as
* Returns the list of classes which have been imported as
* single-class imports.
*
* @param checkIncludes deprecated, no longer used.
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,6 +62,14 @@ public abstract class LookupElement extends UserDataHolderBase {
return this;
}
public boolean isValid() {
final Object object = getObject();
if (object instanceof PsiElement) {
return ((PsiElement)object).isValid();
}
return true;
}
public void handleInsert(InsertionContext context) {
}
@@ -21,13 +21,19 @@ package com.intellij.openapi.project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public class ProjectLocatorImpl extends ProjectLocator {
@Override
@Nullable
public Project guessProjectForFile(final VirtualFile file) {
ProjectManager projectManager = ProjectManager.getInstance();
if (projectManager == null) return null;
if (projectManager == null || file == null) return null;
final Project[] projects = projectManager.getOpenProjects();
if (projects.length == 0) return null;
if (projects.length == 1 && !projects[0].isDisposed()) return projects[0];
@@ -40,4 +46,23 @@ public class ProjectLocatorImpl extends ProjectLocator {
return !projects[0].isDisposed() ? projects[0] : null;
}
@Override
@NotNull
public Collection<Project> getProjectsForFile(VirtualFile file) {
final Collection<Project> result = new HashSet<Project>();
final ProjectManager projectManager = ProjectManager.getInstance();
if (projectManager == null || file == null) { return result; }
final Project[] openProjects = projectManager.getOpenProjects();
if (openProjects.length == 0) { return result; }
for (Project project : openProjects) {
if (project.isInitialized() && !project.isDisposed() && ProjectRootManager.getInstance(project).getFileIndex().isInContent(file)) {
result.add(project);
}
}
return result;
}
}
@@ -10,5 +10,5 @@ public interface AliasingPsiTargetMapper {
ExtensionPointName<AliasingPsiTargetMapper> EP_NAME = ExtensionPointName.create("com.intellij.aliasingPsiTargetMapper");
@NotNull
Set<AliasingPsiTarget> getTargets(@NotNull PomTarget psiTarget);
Set<AliasingPsiTarget> getTargets(@NotNull PomTarget target);
}
@@ -304,15 +304,6 @@ public abstract class OptionTableWithPreviewPanel extends MultilanguageCodeStyle
return false;
}
protected void addOption(Class<? extends CustomCodeStyleSettings> clazz, @NotNull String fieldName, @NotNull String title, @Nullable String groupName) {
myOptions.add(new BooleanOption(clazz, fieldName, title, groupName));
}
protected void addOption(Class<? extends CustomCodeStyleSettings> clazz, @NotNull String fieldName, @NotNull String title, @Nullable String groupName,
@NotNull String[] options, @NotNull int[] values) {
myOptions.add(new SelectionOption(clazz, fieldName, title, groupName, options, values));
}
protected void addOption(@NotNull String fieldName, @NotNull String title) {
addOption(fieldName, title, null);
}
@@ -96,12 +96,8 @@ public class AutoPopupController implements Disposable {
new CodeCompletionHandlerBase(CompletionType.BASIC, false, false).invoke(myProject, editor, file);
}
};
// invoke later prevents cancelling request by keyPressed from the same action
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
myAlarm.addRequest(request, settings.AUTO_LOOKUP_DELAY);
}
});
myAlarm.addRequest(request, settings.AUTO_LOOKUP_DELAY);
}
}
@@ -112,12 +108,7 @@ public class AutoPopupController implements Disposable {
currentCompletion.closeAndFinish();
}
// invoke later prevents cancelling request by keyPressed from the same action
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
myAlarm.addRequest(request, delay);
}
});
myAlarm.addRequest(request, delay);
}
public void autoPopupParameterInfo(final Editor editor, final PsiElement highlightedMethod){
@@ -145,12 +136,8 @@ public class AutoPopupController implements Disposable {
}
}
};
// invoke later prevents cancelling request by keyPressed from the same action
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
myAlarm.addRequest(request, settings.PARAMETER_INFO_DELAY);
}
});
myAlarm.addRequest(request, settings.PARAMETER_INFO_DELAY);
}
}
@@ -539,7 +539,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
}
public boolean isRepeatedInvocation(CompletionType completionType, Editor editor) {
return completionType == myParameters.getCompletionType() && editor == myEditor;
return completionType == myParameters.getCompletionType() && editor == myEditor && !isAutopopupCompletion();
}
@Override
@@ -116,11 +116,8 @@ public class LookupCellRenderer implements ListCellRenderer {
boolean hasFocus) {
if (isSelected && !myLookup.isFocused() && myLookup.isCompletion()) {
//myPanel.setBorder(new DottedBorder(Color.gray));
if (!myLookup.isFocused()) {
isSelected = false;
} else {
//myPanel.setBorder(null);
}
final LookupElement item = (LookupElement)value;
@@ -112,7 +112,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
public LookupImpl(Project project, Editor editor, @NotNull LookupArranger arranger){
super(new JPanel(new BorderLayout()));
setForceShowAsPopup(!SystemInfo.isLinux);
setForceShowAsPopup(true);
myProject = project;
myEditor = editor;
myArranger = arranger;
@@ -42,6 +42,6 @@ public class ChooseItemReplaceAction extends EditorAction {
public void update(Editor editor, Presentation presentation, DataContext dataContext){
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
presentation.setEnabled(lookup != null && lookup.isFocused());
presentation.setEnabled(lookup != null && (lookup.isFocused() || lookup.isCompletion() && !lookup.getItems().isEmpty()));
}
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.actions.CreateFileFromTemplateDialog">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="3" 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="84"/>
@@ -17,21 +17,14 @@
<text value="&amp;Name:"/>
</properties>
</component>
<component id="f8fb3" class="javax.swing.JLabel">
<component id="f8fb3" class="javax.swing.JLabel" binding="myKindLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="48008"/>
<text value="&amp;Kind:"/>
</properties>
</component>
<component id="48008" class="javax.swing.JComboBox" binding="myKindCombo">
<constraints>
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="b76e" class="javax.swing.JTextField" binding="myNameField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
@@ -50,6 +43,17 @@
<toolTipText value="Pressing Up or Down arrows while in editor changes the kind"/>
</properties>
</component>
<vspacer id="115cf">
<constraints>
<grid row="2" column="1" 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="81412" class="com.intellij.ide.actions.TemplateKindCombo" binding="myKindCombo">
<constraints>
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
</form>
@@ -41,60 +41,19 @@ import java.awt.event.KeyEvent;
* @author peter
*/
public class CreateFileFromTemplateDialog extends DialogWrapper {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateFileFromTemplateDialog");
private JTextField myNameField;
private JComboBox myKindCombo;
private TemplateKindCombo myKindCombo;
private JPanel myPanel;
private JLabel myUpDownHint;
private JLabel myKindLabel;
private ElementCreator myCreator;
private CreateFileFromTemplateDialog(@NotNull Project project) {
super(project, true);
myKindCombo.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
@SuppressWarnings({"unchecked"}) Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>) value;
setText(trinity == null ? "" : trinity.first);
setIcon(trinity == null ? null : trinity.second);
return this;
}
});
//myNameLabel.setText(prompt);
new ComboboxSpeedSearch(myKindCombo) {
@Override
protected String getElementText(Object element) {
return ((Trinity<String, Icon, String>)element).first;
}
};
final AnAction arrow = new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
if (e.getInputEvent() instanceof KeyEvent) {
final int code = ((KeyEvent)e.getInputEvent()).getKeyCode();
final int delta = code == KeyEvent.VK_DOWN ? 1 : code == KeyEvent.VK_UP ? -1 : 0;
final int size = myKindCombo.getModel().getSize();
int next = myKindCombo.getSelectedIndex() + delta;
if (next < 0 || next >= size) {
if (!UISettings.getInstance().CYCLE_SCROLLING) {
return;
}
next = (next + size) % size;
}
myKindCombo.setSelectedIndex(next);
}
}
};
final KeyboardShortcut up = new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), null);
final KeyboardShortcut down = new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), null);
arrow.registerCustomShortcutSet(new CustomShortcutSet(up, down), myNameField);
myKindLabel.setLabelFor(myKindCombo);
myKindCombo.registerUpDownHint(myNameField);
myUpDownHint.setIcon(Icons.UP_DOWN_ARROWS);
init();
}
@@ -103,16 +62,6 @@ public class CreateFileFromTemplateDialog extends DialogWrapper {
return myNameField.getText();
}
private String getTemplateName() {
//noinspection unchecked
final Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>)myKindCombo.getSelectedItem();
if (trinity == null) {
LOG.error("Model: " + myKindCombo.getModel());
}
return trinity.third;
}
@Override
protected JComponent createCenterPanel() {
return myPanel;
@@ -143,36 +92,23 @@ public class CreateFileFromTemplateDialog extends DialogWrapper {
}
public Builder addKind(@NotNull String name, @Nullable Icon icon, @NotNull String templateName) {
dialog.myKindCombo.addItem(new Trinity<String, Icon, String>(name, icon, templateName));
dialog.myKindCombo.addItem(name, icon, templateName);
return this;
}
public <T extends PsiElement> T show(@NotNull String errorTitle, @Nullable String selectedTemplateName,
@NotNull final FileCreator<T> creator) {
final Ref<T> created = Ref.create(null);
if (selectedTemplateName != null) {
Object item = null;
ComboBoxModel model = dialog.myKindCombo.getModel();
for (int i = 0, n = model.getSize(); i < n; i++) {
Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>)model.getElementAt(i);
if (selectedTemplateName.equals(trinity.third)) {
item = trinity;
break;
}
}
if (item != null) {
dialog.myKindCombo.setSelectedItem(item);
}
}
dialog.myKindCombo.setSelectedName(selectedTemplateName);
dialog.myCreator = new ElementCreator(project, errorTitle) {
@Override
protected void checkBeforeCreate(String newName) throws IncorrectOperationException {
creator.checkBeforeCreate(newName, dialog.getTemplateName());
creator.checkBeforeCreate(newName, dialog.myKindCombo.getSelectedName());
}
@Override
protected PsiElement[] create(String newName) throws Exception {
final T element = creator.createFile(dialog.getEnteredName(), dialog.getTemplateName());
final T element = creator.createFile(dialog.getEnteredName(), dialog.myKindCombo.getSelectedName());
created.set(element);
if (element != null) {
return new PsiElement[]{element};
@@ -182,7 +118,7 @@ public class CreateFileFromTemplateDialog extends DialogWrapper {
@Override
protected String getActionName(String newName) {
return creator.getActionName(newName, dialog.getTemplateName());
return creator.getActionName(newName, dialog.myKindCombo.getSelectedName());
}
};
dialog.show();
@@ -0,0 +1,119 @@
/*
* Copyright 2000-2010 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.ide.actions;
import com.intellij.ide.ui.ListCellRendererWrapper;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Trinity;
import com.intellij.ui.ComboboxSpeedSearch;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.KeyEvent;
public class TemplateKindCombo extends JComboBox {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.TemplateKindCombo");
public TemplateKindCombo() {
super();
setRenderer(new ListCellRendererWrapper(getRenderer()) {
@Override
public String getDisplayedName(Object value) {
if (value instanceof Trinity) {
return (String)((Trinity)value).first;
}
return null;
}
@Override
public Icon getIcon(Object value) {
if (value instanceof Trinity) {
return (Icon)((Trinity)value).second;
}
return null;
}
});
new ComboboxSpeedSearch(this) {
@Override
protected String getElementText(Object element) {
if (element instanceof Trinity) {
return (String)((Trinity)element).first;
}
return null;
}
};
}
public void addItem(String presentableName, Icon icon, String templateName) {
addItem(new Trinity<String, Icon, String>(presentableName, icon, templateName));
}
public String getSelectedName() {
//noinspection unchecked
final Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>)getSelectedItem();
if (trinity == null) {
LOG.error("Model: " + getModel());
}
return trinity.third;
}
public void setSelectedName(@Nullable String name) {
if (name == null) return;
ComboBoxModel model = getModel();
for (int i = 0, n = model.getSize(); i < n; i++) {
Trinity<String, Icon, String> trinity = (Trinity<String, Icon, String>)model.getElementAt(i);
if (name.equals(trinity.third)) {
setSelectedItem(trinity);
return;
}
}
}
public void registerUpDownHint(JComponent component) {
final AnAction arrow = new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
if (e.getInputEvent() instanceof KeyEvent) {
final int code = ((KeyEvent)e.getInputEvent()).getKeyCode();
scrollBy(code == KeyEvent.VK_DOWN ? 1 : code == KeyEvent.VK_UP ? -1 : 0);
}
}
};
final KeyboardShortcut up = new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), null);
final KeyboardShortcut down = new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), null);
arrow.registerCustomShortcutSet(new CustomShortcutSet(up, down), component);
}
private void scrollBy(int delta) {
final int size = getModel().getSize();
int next = getSelectedIndex() + delta;
if (next < 0 || next >= size) {
if (!UISettings.getInstance().CYCLE_SCROLLING) {
return;
}
next = (next + size) % size;
}
setSelectedIndex(next);
}
}
@@ -34,8 +34,10 @@ public class NavigatableRule implements GetDataRule {
return openFileDescriptor;
}
}
final PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataProvider);
if (element instanceof Navigatable) {
return element;
}
if (element != null) {
return EditSourceUtil.getDescriptor(element);
}
@@ -16,28 +16,31 @@
package com.intellij.ide.scriptingContext;
import com.intellij.ide.scriptingContext.ui.ScriptingLibrariesPanel;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.libraries.LibraryTable;
import org.jetbrains.annotations.Nls;
import javax.swing.*;
/**
* @author Rustam Vishnyakov <dyadix@gmail.com>
* @author Rustam Vishnyakov
*/
public class LangScriptingContextConfigurable implements Configurable {
private ScriptingLibrariesPanel myPanel;
private LangScriptingContextProvider myProvider;
private ModifiableRootModel myRootModel;
public LangScriptingContextConfigurable(Project project, LangScriptingContextProvider provider) {
myRootModel = ScriptingLibraryManager.getRootModel(project);
if (myRootModel != null) {
myPanel = new ScriptingLibrariesPanel(myRootModel.getModuleLibraryTable());
}
public LangScriptingContextConfigurable(ModifiableRootModel rootModel, LangScriptingContextProvider provider) {
LibraryTable libTable = rootModel != null ?
rootModel.getModuleLibraryTable() : null;
myPanel = new ScriptingLibrariesPanel(libTable);
myProvider = provider;
myRootModel = rootModel;
}
@Nls
@@ -63,12 +66,19 @@ public class LangScriptingContextConfigurable implements Configurable {
@Override
public boolean isModified() {
return false; //To change body of implemented methods use File | Settings | File Templates.
return myPanel.isModified();
}
@Override
public void apply() throws ConfigurationException {
//To change body of implemented methods use File | Settings | File Templates.
if (myRootModel != null) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
myRootModel.commit();
}
});
}
}
@Override
@@ -78,6 +88,6 @@ public class LangScriptingContextConfigurable implements Configurable {
@Override
public void disposeUIResources() {
myRootModel.dispose();
}
}
@@ -16,9 +16,11 @@
package com.intellij.ide.scriptingContext;
import com.intellij.ide.scriptingContext.ui.MainScriptingContextsPanel;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import org.jetbrains.annotations.Nls;
import javax.swing.*;
@@ -32,11 +34,13 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
private MainScriptingContextsPanel myPanel;
private String myLangNames;
private Project myProject;
private ModifiableRootModel myRootModel;
public ScriptingContextsConfigurable(Project project) {
myPanel = new MainScriptingContextsPanel();
myLangNames = getLangNames();
myProject = project;
myRootModel = ScriptingLibraryManager.getRootModel(project);
}
@Nls
@@ -67,7 +71,9 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
@Override
public void apply() throws ConfigurationException {
//To change body of implemented methods use File | Settings | File Templates.
if (myRootModel != null) {
myRootModel.commit();
}
}
@Override
@@ -77,14 +83,14 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
@Override
public void disposeUIResources() {
//To change body of implemented methods use File | Settings | File Templates.
disposeModel();
}
@Override
public Configurable[] getConfigurables() {
ArrayList<LangScriptingContextConfigurable> configurables = new ArrayList<LangScriptingContextConfigurable>();
for (LangScriptingContextProvider provider : LangScriptingContextProvider.getProviders()) {
configurables.add(new LangScriptingContextConfigurable(myProject, provider));
configurables.add(new LangScriptingContextConfigurable(myRootModel, provider));
}
return configurables.toArray(new LangScriptingContextConfigurable[configurables.size()]);
}
@@ -97,4 +103,10 @@ public class ScriptingContextsConfigurable implements Configurable, Configurable
String result = buf.toString();
return result.substring(0, result.length() - 1);
}
public void disposeModel() {
if (myRootModel != null && !myRootModel.isDisposed()) {
myRootModel.dispose();
}
}
}
@@ -36,4 +36,8 @@ public class EditLibraryDialog extends DialogWrapper {
protected JComponent createCenterPanel() {
return contentPane;
}
public String getLibName() {
return myLibName.getText();
}
}
@@ -29,7 +29,7 @@
</component>
</children>
</scrollpane>
<component id="76cd4" class="javax.swing.JButton" binding="myAddLibrarytButton">
<component id="76cd4" class="javax.swing.JButton" binding="myAddLibraryButton">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
@@ -45,7 +45,7 @@
<text value="Remove"/>
</properties>
</component>
<component id="7d17d" class="javax.swing.JButton" binding="myEditLibrarytButton">
<component id="7d17d" class="javax.swing.JButton" binding="myEditLibraryButton">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
@@ -15,10 +15,7 @@
*/
package com.intellij.ide.scriptingContext.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.ui.components.JBList;
import com.intellij.ui.table.JBTable;
import javax.swing.*;
@@ -30,20 +27,29 @@ import java.awt.event.ActionListener;
*/
public class ScriptingLibrariesPanel {
private JPanel myTopPanel;
private JButton myAddLibrarytButton;
private JButton myAddLibraryButton;
private JButton myRemoveLibraryButton;
private JButton myEditLibrarytButton;
private JButton myEditLibraryButton;
private JPanel myScriptingLibrariesPanel;
private JBTable myLibraryTable;
private ScriptingLibraryTableModel myLibTableModel;
private boolean myModified;
public ScriptingLibrariesPanel(LibraryTable libTable) {
myLibraryTable.setModel(new ScriptingLibraryTableModel(libTable));
myAddLibrarytButton.addActionListener(new ActionListener(){
myLibTableModel = new ScriptingLibraryTableModel(libTable);
myLibraryTable.setModel(myLibTableModel);
myAddLibraryButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
addLibrary();
}
});
if (libTable == null) {
myAddLibraryButton.setEnabled(false);
}
myRemoveLibraryButton.setEnabled(false);
myEditLibraryButton.setEnabled(false);
myModified = false;
}
public JPanel getPanel() {
@@ -54,8 +60,18 @@ public class ScriptingLibrariesPanel {
EditLibraryDialog editLibDialog = new EditLibraryDialog();
editLibDialog.show();
if (editLibDialog.isOK()) {
//TODO: Implement
createLibrary(editLibDialog.getLibName());
myModified = true;
}
}
private void createLibrary(String name) {
myLibTableModel.getLibraryTable().createLibrary(name);
myLibraryTable.repaint();
}
public boolean isModified() {
return myModified;
}
}
@@ -38,7 +38,10 @@ public class ScriptingLibraryTableModel extends AbstractTableModel {
@Override
public int getRowCount() {
return myLibTable.getLibraries().length;
if (myLibTable != null) {
return myLibTable.getLibraries().length;
}
return 0;
}
@Override
@@ -62,4 +65,8 @@ public class ScriptingLibraryTableModel extends AbstractTableModel {
return "?";
}
public LibraryTable getLibraryTable() {
return myLibTable;
}
}
@@ -924,6 +924,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
}
else if (item instanceof DoneMarker) {
curNode = nodes.pop();
item.next = i < myProduction.size() - 1 ? myProduction.get(i + 1) : null;
}
else if (item instanceof ErrorItem) {
int curToken = item.myLexemeIndex;
@@ -986,10 +987,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
CompositeElement curNode = rootNode;
int lexIndex = rootMarker.myLexemeIndex;
int lastErrorIndex = -1;
for (int i = myProduction.indexOf(rootMarker) + 1; i <= myProduction.indexOf(rootMarker.myDoneMarker); i++) {
final ProductionMarker item = myProduction.get(i);
ProductionMarker item = rootMarker.firstChild != null ? rootMarker.firstChild : rootMarker.myDoneMarker;
while (item != null) {
lexIndex = insertLeaves(lexIndex, item.myLexemeIndex, curNode);
if (item instanceof StartMarker) {
@@ -1002,25 +1001,24 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
curNode.rawAddChildren(childNode);
nodes.push(curNode);
curNode = childNode;
item = marker.firstChild != null ? marker.firstChild : marker.myDoneMarker;
}
else {
lexIndex = collapseLeaves(curNode, marker);
//noinspection AssignmentToForLoopParameter
i = myProduction.indexOf(marker.myDoneMarker);
item = marker.myDoneMarker.next;
}
}
else if (item instanceof ErrorItem) {
final PsiErrorElementImpl errorElement = new PsiErrorElementImpl();
errorElement.setErrorDescription(((ErrorItem)item).myMessage);
curNode.rawAddChildren(errorElement);
item = item.next != null ? item.next : curMarker.myDoneMarker;
}
else if (item instanceof DoneMarker) {
curMarker = markers.pop();
curNode = nodes.pop();
}
else if (item instanceof ErrorItem) {
int curToken = item.myLexemeIndex;
if (curToken == lastErrorIndex) continue;
lastErrorIndex = curToken;
final PsiErrorElementImpl errorElement = new PsiErrorElementImpl();
errorElement.setErrorDescription(((ErrorItem)item).myMessage);
curNode.rawAddChildren(errorElement);
item = item.next;
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.changeSignature;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
@@ -29,6 +30,7 @@ import com.intellij.openapi.editor.event.EditorFactoryListener;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
@@ -92,13 +94,17 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme
public void projectOpened() {
myPsiManager.addPsiTreeChangeListener(this);
EditorFactory.getInstance().addEditorFactoryListener(this);
Disposer.register(myPsiManager.getProject(), new Disposable() {
public void dispose() {
myPsiManager.removePsiTreeChangeListener(ChangeSignatureGestureDetector.this);
EditorFactory.getInstance().removeEditorFactoryListener(ChangeSignatureGestureDetector.this);
myListenerMap.clear();
}
});
}
@Override
public void projectClosed() {
myListenerMap.clear();
myPsiManager.removePsiTreeChangeListener(this);
EditorFactory.getInstance().removeEditorFactoryListener(this);
}
@NotNull
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2010 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.
@@ -213,7 +213,7 @@ public class BrowserUtil {
@NotNull
public static String escapeUrl(@NotNull @NonNls String url) {
if (SystemInfo.isWindows) {
return url.indexOf(' ') > 0? "\"" + url + "\"" : url;
return (url.indexOf(' ') > 0 || url.indexOf('&') > -1) ? "\"" + url + "\"" : url;
}
else {
return url.replaceAll(" ", "%20");
@@ -383,15 +383,11 @@ public class BrowserUtil {
}
public static boolean canStartDefaultBrowser() {
if (SystemInfo.isMac) {
if (SystemInfo.isMac || SystemInfo.isWindows) {
return true;
}
if (SystemInfo.isWindows) {
return true;
}
if (SystemInfo.isLinux && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
if (SystemInfo.isLinux && Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
return true;
}
@@ -21,13 +21,33 @@ package com.intellij.openapi.project;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public abstract class ProjectLocator {
public static ProjectLocator getInstance() {
return ServiceManager.getService(ProjectLocator.class);
}
/**
* Returns an open project which contains the given file.
* This is a guess-method, so if several projects contain the file, only one will be returned.
* Also a project may be returned though it doesn't contain the file for sure (see implementations).
* @param file file to be located in projects.
* @return project which probably contains the file, or null if couldn't guess (for example, there are no open projects).
*/
@Nullable
public abstract Project guessProjectForFile(VirtualFile file);
/**
* Gets all open projects containing the given file.
* If none does, an empty list is returned.
* @param file file to be located in projects.
* @return list of open projects containing this file.
*/
@NotNull
public abstract Collection<Project> getProjectsForFile(VirtualFile file);
}
@@ -219,6 +219,17 @@ public class Messages {
return showDialog(message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, 0, icon);
}
public static int shpwTwoStepConfirmationDialog(String message, String title, String checkboxText, Icon icon) {
if (isApplicationInUnitTestOrHeadless()) {
return ourTestImplementation.show(message);
}
else {
TwoStepConfirmationDialog dialog = new TwoStepConfirmationDialog(message, title, checkboxText, icon);
dialog.show();
return dialog.getExitCode();
}
}
public static void showErrorDialog(Project project, @Nls String message, @Nls String title) {
showDialog(project, message, title, new String[]{OK_BUTTON}, 0, getErrorIcon());
}
@@ -548,7 +559,11 @@ public class Messages {
this(message, title, options, defaultOptionIndex, -1, icon, doNotAskOption);
}
private void _init(String title, String message, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon, DoNotAskOption doNotAskOption) {
protected MessageDialog() {
super(false);
}
protected void _init(String title, String message, String[] options, int defaultOptionIndex, int focusedOptionIndex, Icon icon, DoNotAskOption doNotAskOption) {
setTitle(title);
myMessage = message;
myOptions = options;
@@ -673,6 +688,62 @@ public class Messages {
}
}
protected static class TwoStepConfirmationDialog extends MessageDialog {
private JCheckBox myCheckBox;
private String myCheckboxText;
public TwoStepConfirmationDialog(String message, String title, String checkboxText, Icon icon) {
myCheckboxText = checkboxText;
_init(title, message, new String[] {OK_BUTTON, CANCEL_BUTTON}, -1, -1, icon, null);
}
@Override
protected JComponent createNorthPanel() {
JPanel panel = new JPanel(new BorderLayout(15, 0));
if (myIcon != null) {
JLabel iconLabel = new JLabel(myIcon);
Container container = new Container();
container.setLayout(new BorderLayout());
container.add(iconLabel, BorderLayout.NORTH);
panel.add(container, BorderLayout.WEST);
}
JPanel messagePanel = new JPanel(new BorderLayout());
if (myMessage != null) {
JLabel textLabel = new JLabel(myMessage);
textLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
textLabel.setUI(new MultiLineLabelUI());
messagePanel.add(textLabel, BorderLayout.NORTH);
}
final JPanel checkboxPanel = new JPanel();
checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.X_AXIS));
myCheckBox = new JCheckBox(myCheckboxText);
myCheckBox.setSelected(true);
messagePanel.add(myCheckBox, BorderLayout.SOUTH);
panel.add(messagePanel, BorderLayout.CENTER);
return panel;
}
@Override
public int getExitCode() {
final int exitCode = super.getExitCode();
return exitCode == OK_EXIT_CODE ? myCheckBox.isSelected() ? OK_EXIT_CODE : CANCEL_EXIT_CODE : CANCEL_EXIT_CODE;
}
@Override
public JComponent getPreferredFocusedComponent() {
return myCheckBox;
}
@Override
protected JComponent createCenterPanel() {
return null;
}
}
protected static class InputDialog extends MessageDialog {
private JTextComponent myField;
private InputValidator myValidator;
@@ -25,6 +25,7 @@ import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public class Registry {
@@ -35,8 +36,7 @@ public class Registry {
private final LinkedHashMap<String, String> myUserProperties = new LinkedHashMap<String, String>();
private final Map<String, String> myLoadedUserProperties = new HashMap<String, String>();
private final Map<String, RegistryValue> myValues = new HashMap<String, RegistryValue>();
private final Map<String, RegistryValue> myValues = new ConcurrentHashMap<String, RegistryValue>();
private static final Registry ourInstance = new Registry();
@@ -56,6 +56,11 @@ public class VFileCreateEvent extends VFileEvent {
return myParent.getPath() + "/" + myChildName;
}
@Override
public VirtualFile getFile() {
return myParent.findChild(myChildName);
}
public VirtualFileSystem getFileSystem() {
return myParent.getFileSystem();
}
@@ -19,7 +19,9 @@
*/
package com.intellij.openapi.vfs.newvfs.events;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;
import org.jetbrains.annotations.Nullable;
public abstract class VFileEvent {
private final boolean myIsFromRefresh;
@@ -40,6 +42,13 @@ public abstract class VFileEvent {
public abstract String getPath();
/**
* Returns the VirtualFile which this event belongs to.
* In some cases it may be null - it is not guaranteed that there is such file.
*/
@Nullable
public abstract VirtualFile getFile();
public abstract VirtualFileSystem getFileSystem();
public abstract boolean isValid();
@@ -171,8 +171,31 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
public void paint(Graphics g) {
final Rectangle visible = getVisibleRect();
if (!AbstractTreeBuilder.isToPaintSelection(this)) {
mySelectionModel.holdSelection();
boolean canHoldSelection = false;
TreePath[] paths = getSelectionModel().getSelectionPaths();
if (paths != null) {
for (TreePath each : paths) {
Rectangle selection = getPathBounds(each);
if (g.getClipBounds().intersects(selection) || g.getClipBounds().contains(selection)) {
if (myBusy) {
Rectangle busyIconBounds = myBusyIcon.getBounds();
if (selection.contains(busyIconBounds) || selection.intersects(busyIconBounds)) {
canHoldSelection = false;
break;
} else {
canHoldSelection = true;
}
} else {
canHoldSelection = true;
}
}
}
}
if (canHoldSelection) {
if (!AbstractTreeBuilder.isToPaintSelection(this)) {
mySelectionModel.holdSelection();
}
}
try {
@@ -121,50 +121,78 @@ class UndoRedoStacksHolder {
}
public void addToStacks(UndoableGroup group) {
if (group.isGlobal()) doAddToStack(myGlobalStack, group, UndoManagerImpl.GLOBAL_UNDO_LIMIT);
for (DocumentReference each : group.getAffectedDocuments()) {
doAddToStack(getStack(each), group, UndoManagerImpl.LOCAL_UNDO_LIMIT);
for (LinkedList<UndoableGroup> each : getAffectedStacks(group)) {
doAddToStack(each, group, each == myGlobalStack ? UndoManagerImpl.GLOBAL_UNDO_LIMIT : UndoManagerImpl.LOCAL_UNDO_LIMIT);
}
}
private void doAddToStack(LinkedList<UndoableGroup> stack, UndoableGroup group, int limit) {
if (!group.isUndoable() && stack.isEmpty()) return;
stack.addLast(group);
while (stack.size() > limit) {
stack.removeFirst();
clearStacksFrom(stack.getFirst());
}
}
public void removeFromStacks(UndoableGroup group) {
if (group.getAffectedDocuments().isEmpty()) return;
if (group.isGlobal()) {
assert myGlobalStack.getLast() == group;
myGlobalStack.removeLast();
}
for (DocumentReference each : group.getAffectedDocuments()) {
LinkedList<UndoableGroup> stack = getStack(each);
assert stack.getLast() == group;
stack.removeLast();
for (LinkedList<UndoableGroup> each : getAffectedStacks(group)) {
assert each.getLast() == group;
each.removeLast();
}
}
public void clearStacks(boolean clearGlobal, Set<DocumentReference> affectedDocuments) {
if (clearGlobal) myGlobalStack.clear();
for (DocumentReference ref : affectedDocuments) {
List<UndoableGroup> stack = getStack(ref);
stack.clear();
if (ref.getFile() != null) {
myDocumentStacks.remove(ref);
}
else {
Document d = ref.getDocument();
d.putUserData(STACK_IN_DOCUMENT_KEY, null);
myDocumentsWithStacks.remove(d);
public void clearStacks(boolean clearGlobal, Set<DocumentReference> refs) {
for (LinkedList<UndoableGroup> each : getAffectedStacks(clearGlobal, refs)) {
while(!each.isEmpty()) {
clearStacksFrom(each.getLast());
}
}
Set<DocumentReference> stacksToDrop = new THashSet<DocumentReference>();
for (Map.Entry<DocumentReference, LinkedList<UndoableGroup>> each : myDocumentStacks.entrySet()) {
if (each.getValue().isEmpty()) stacksToDrop.add(each.getKey());
}
for (DocumentReference each : stacksToDrop) {
myDocumentStacks.remove(each);
}
Set<Document> docsToDrop = new THashSet<Document>();
for (Document each : myDocumentsWithStacks) {
LinkedList<UndoableGroup> stack = each.getUserData(STACK_IN_DOCUMENT_KEY);
if (stack != null && stack.isEmpty()) {
each.putUserData(STACK_IN_DOCUMENT_KEY, null);
docsToDrop.add(each);
}
}
myDocumentsWithStacks.removeAll(docsToDrop);
}
private void clearStacksFrom(UndoableGroup from) {
for (LinkedList<UndoableGroup> each : getAffectedStacks(from)) {
int pos = each.indexOf(from);
if (pos == -1) continue;
if (pos > 0) {
int top = each.size() - pos;
clearStacksFrom(each.get(pos - 1));
assert each.size() == top && each.indexOf(from) == 0;
}
each.removeFirst();
}
}
private List<LinkedList<UndoableGroup>> getAffectedStacks(UndoableGroup group) {
return getAffectedStacks(group.isGlobal(), group.getAffectedDocuments());
}
private List<LinkedList<UndoableGroup>> getAffectedStacks(boolean global, Collection<DocumentReference> refs) {
List<LinkedList<UndoableGroup>> result = new ArrayList<LinkedList<UndoableGroup>>();
if (global) result.add(myGlobalStack);
for (DocumentReference each : refs) {
result.add(getStack(each));
}
return result;
}
public void clearAllStacksInTests() {
@@ -513,6 +513,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (myInitialMouseEvent != null) {
myIgnoreMouseEventsConsecutiveToInitial = true;
}
// There is a possible case that 'use soft wrap' setting value is changed and we need to repaint all affected lines then.
repaintToScreenBottom(getCaretModel().getLogicalPosition().line);
int y = getCaretModel().getVisualLineStart() * getLineHeight();
myGutterComponent.repaint(0, y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - y);
getCaretModel().moveToOffset(getCaretModel().getOffset());
}
private void initTabPainter() {
@@ -933,60 +939,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
offset = region.getEndOffset();
}
else {
//SoftWrap softWrap = mySoftWrapModel.getSoftWrap(offset);
//if (softWrap != null) {
// // There is a possible case that soft wrap contains more than one line feed inside and we need to start counting not
// // from its first line.
// int softWrapLinesToSkip = activeSoftWrapProcessed ? 0 : logicalPosition.softWrapLinesOnCurrentLogicalLine;
//
// // Process 'before soft wrap' drawing.
// if (softWrapLinesToSkip <= 0) {
// prevX = x;
// charWidth = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
// x += charWidth;
// if (x >= px) {
// onSoftWrapDrawing = true;
// break outer;
// }
// column++;
// }
//
// CharSequence softWrapText = softWrap.getText();
// for (int i = 0; i < softWrapText.length(); i++) {
// c = softWrapText.charAt(i);
// if (softWrapLinesToSkip > 0) {
// if (c == '\n') {
// softWrapLinesToSkip--;
// }
// continue;
// }
// prevX = x;
//
// charWidth = charToVisibleWidth(c, fontType, x);
// if (charWidth == 0) {
// charWidth = spaceSize;
// break outer;
// }
//
// x += charWidth;
// if (x >= px) {
// break outer;
// }
// column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
// }
// activeSoftWrapProcessed = true;
//
// // Process 'after soft wrap' sign.
// prevX = x;
// charWidth = mySoftWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
// x += charWidth;
// if (x >= px) {
// onSoftWrapDrawing = true;
// break outer;
// }
// column++;
//}
prevX = x;
c = text.charAt(offset);
charWidth = charToVisibleWidth(c, fontType, x);
@@ -1091,24 +1043,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private int logicalToVisualLine(int line) {
assertReadAccess();
return logicalToVisualPosition(new LogicalPosition(line, 0)).line;
//if (!myFoldingModel.isFoldingEnabled()) return line;
//
//
//int offset = line >= myDocument.getLineCount() ? myDocument.getTextLength() : myDocument.getLineStartOffset(line);
//
//FoldRegion outermostCollapsed = myFoldingModel.getCollapsedRegionAtOffset(offset);
//if (outermostCollapsed != null && offset > outermostCollapsed.getStartOffset()) {
// if (offset < getDocument().getTextLength()) {
// offset = outermostCollapsed.getStartOffset();
// return offsetToVisualLine(offset);
// }
// else {
// offset = outermostCollapsed.getEndOffset() + 3; // WTF?
// }
//}
//
//line -= myFoldingModel.getFoldedLinesCountBefore(offset);
//return line;
}
@NotNull
@@ -1707,6 +1641,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return;
}
boolean locateBeforeSoftWrap = !SoftWrapHelper.isCaretAfterSoftWrap(this);
int start = logicalPositionToOffset(logicalPosition);
getSoftWrapModel().registerSoftWrapsIfNecessary(clip, start);
@@ -1807,22 +1742,21 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
paintAfterFileEndBackground(iterationState, g, position, clip, lineHeight, defaultBackground, caretRowPainted);
}
//TODO den check
// Perform additional activity if soft wrap is added or removed during repainting.
//if (mySoftWrapsChanged) {
// mySoftWrapsChanged = false;
// validateSize();
//
// // Repaint editor to the bottom in order to ensure that its content is shown correctly after new soft wrap introduction.
// repaintToScreenBottom(xyToLogicalPosition(position).line);
//
// // Repaint gutter at all space that is located after active clip in order to ensure that line numbers are correctly redrawn
// // in accordance with the newly introduced soft wrap(s).
// myGutterComponent.repaint(0, clip.y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - clip.y);
//
// // Ask caret model to update visual caret position.
// getCaretModel().moveToOffset(getCaretModel().getOffset(), locateBeforeSoftWrap);
//}
if (mySoftWrapsChanged) {
mySoftWrapsChanged = false;
validateSize();
// Repaint editor to the bottom in order to ensure that its content is shown correctly after new soft wrap introduction.
repaintToScreenBottom(xyToLogicalPosition(position).line);
// Repaint gutter at all space that is located after active clip in order to ensure that line numbers are correctly redrawn
// in accordance with the newly introduced soft wrap(s).
myGutterComponent.repaint(0, clip.y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - clip.y);
// Ask caret model to update visual caret position.
getCaretModel().moveToOffset(getCaretModel().getOffset(), locateBeforeSoftWrap);
}
}
private void paintRectangularSelection(Graphics g) {
@@ -4326,13 +4260,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (myCommandProcessor != null) {
Runnable runnable = new Runnable() {
public void run() {
processMousePressed(e, e.getSource() == getContentComponent());
processMousePressed(e);
}
};
myCommandProcessor.executeCommand(myProject, runnable, "", DocCommandGroupId.noneGroupId(getDocument()), UndoConfirmationPolicy.DEFAULT, getDocument());
}
else {
processMousePressed(e, e.getSource() == getContentComponent());
processMousePressed(e);
}
}
@@ -4393,7 +4327,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
private void processMousePressed(MouseEvent e, boolean moveCaretToClickPosition) {
private void processMousePressed(MouseEvent e) {
myInitialMouseEvent = e;
if (myMouseSelectionState != MOUSE_SELECTION_STATE_NONE && System.currentTimeMillis() - myMouseSelectionChangeTimestamp > 1000) {
@@ -4435,9 +4369,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
int oldSelectionStart = mySelectionModel.getLeadSelectionOffset();
if (moveCaretToClickPosition) {
moveCaretToScreenPos(x, y);
}
moveCaretToScreenPos(x, y);
if (e.isPopupTrigger()) return;
@@ -367,7 +367,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList
myCaretPositionSaved = oldCaretPositionSaved;
if (!hasBlockSelection) {
if (!hasBlockSelection && selectionStart < myEditor.getDocument().getTextLength()) {
myEditor.getSelectionModel().setSelection(selectionStart, selectionEnd);
}
@@ -438,9 +438,10 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
LOG.info(" documentStamp:" + documentStamp);
LOG.info(" oldFileStamp:" + oldFileStamp);
final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
Runnable askReloadRunnable = new Runnable() {
public void run() {
IdeEventQueue.getInstance().removeIdleListener(this);
if (!unitTestMode) IdeEventQueue.getInstance().removeIdleListener(this);
if (!file.isValid()) return;
if (askReloadFromDisk(file, document)) {
reloadFromDisk(document);
@@ -448,7 +449,11 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl
}
};
IdeEventQueue.getInstance().addIdleListener(askReloadRunnable, 2000);
if (unitTestMode) {
askReloadRunnable.run();
} else {
IdeEventQueue.getInstance().addIdleListener(askReloadRunnable, 2000);
}
}
else {
reloadFromDisk(document);
@@ -23,8 +23,14 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectLocator;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
public class DefaultProjectLocator extends ProjectLocator {
@Nullable
public Project guessProjectForFile(final VirtualFile file) {
@@ -39,4 +45,14 @@ public class DefaultProjectLocator extends ProjectLocator {
return null;
}
}
@NotNull
@Override
public Collection<Project> getProjectsForFile(VirtualFile file) {
final ProjectManager projectManager = ProjectManager.getInstance();
if (projectManager == null || file == null) { return new HashSet<Project>(); }
final Project[] openProjects = projectManager.getOpenProjects();
return Arrays.asList(openProjects);
}
}
@@ -693,7 +693,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
message = ProjectBundle.message("project.reload.external.change.multiple", filesBuilder.toString());
}
return Messages.showYesNoDialog(project, message, ProjectBundle.message("project.reload.external.change.title"), Messages.getQuestionIcon()) == 0;
return Messages.shpwTwoStepConfirmationDialog(message, ProjectBundle.message("project.reload.external.change.title"), "Reload project", Messages.getQuestionIcon()) == 0;
}
public boolean isFileSavedToBeReloaded(VirtualFile candidate) {
@@ -37,7 +37,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.GeneralPath;
@@ -234,10 +233,10 @@ public class BalloonImpl implements Disposable, Balloon, LightweightWindow, Posi
}
private void show(PositionTracker<Balloon> tracker, Position position) {
if (isVisible()) return;
assert !myDisposed : "Balloon is already disposed";
assert tracker.getComponent().isShowing() : "Target component is not showing: " + tracker;
if (isVisible()) return;
if (!tracker.getComponent().isShowing()) return;
myTracker = tracker;
myTracker.init(this);
@@ -13,8 +13,8 @@ project.load.undefined.path.variables.all.needed=All path variables should be de
project.load.undefined.path.variables.title=Path Variables Not Defined
project.load.default.error=Error Loading Default Project
project.load.progress=Loading Project
project.reload.external.change.single=Project file {0} has been changed externally.\n\nReload project?
project.reload.external.change.multiple=Project files:\n{0}\nhave been changed externally.\n\nReload project?
project.reload.external.change.single=Project file {0} has been changed externally.\nIt is recommended to reload project for changes to take effect.
project.reload.external.change.multiple=Project files:\n{0}\nhave been changed externally.\nIt is recommended to reload project for changes to take effect.
project.reload.external.change.title=Project Files Changed
project.reload.write.failed=Error writing to file ''{0}''. Project may reload incorrectly.
project.reload.write.failed.title=Write error
@@ -181,13 +181,23 @@ public class AbstractVcsTestCase {
return result.get();
}
/**
* Creates directory inside a write action and returns the resulting reference to it.
* If the directory already exists, does nothing.
* @param parent Parent directory.
* @param name Name of the directory.
* @return reference to the created or already existing directory.
*/
protected VirtualFile createDirInCommand(final VirtualFile parent, final String name) {
final Ref<VirtualFile> result = new Ref<VirtualFile>();
new WriteCommandAction.Simple(myProject) {
@Override
protected void run() throws Throwable {
try {
VirtualFile dir = parent.createChildDirectory(this, name);
VirtualFile dir = parent.findChild(name);
if (dir == null) {
dir = parent.createChildDirectory(this, name);
}
result.set(dir);
}
catch (IOException e) {
@@ -317,6 +327,10 @@ public class AbstractVcsTestCase {
}.execute();
}
protected void editFileInCommand(final VirtualFile file, final String newContent) {
editFileInCommand(myProject, file, newContent);
}
public static void editFileInCommand(final Project project, final VirtualFile file, final String newContent) {
new WriteCommandAction.Simple(project) {
@Override
@@ -1060,6 +1060,14 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
myProjectFixture.tearDown();
myTempDirFixture.tearDown();
myEditor = null;
myFile = null;
myPsiManager = null;
myInspections = null;
myAvailableLocalTools.clear();
myAvailableTools.clear();
myFileContext = null;
super.tearDown();
}
@@ -19,10 +19,10 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import dk.brics.automaton.Automaton;
import dk.brics.automaton.DatatypesAutomatonProvider;
import dk.brics.automaton.RegExp;
import dk.brics.automaton.RunAutomaton;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -384,17 +384,19 @@ public class NameUtil {
private static class OptimizedMatcher implements Matcher {
private final char[] myPreparedPattern;
private final boolean myEnsureFirstSymbolsMatch;
private final RunAutomaton myRunAutomaton;
private final Perl5Matcher myMatcher;
private final Pattern myPattern;
public OptimizedMatcher(String pattern, String regexp) {
myPreparedPattern = preparePattern(pattern).toCharArray();
myEnsureFirstSymbolsMatch = pattern.length() > 0 && Character.isLetterOrDigit(pattern.charAt(0));
//final long t = System.currentTimeMillis();
final RegExp regExp = new RegExp(regexp);
final Automaton automaton = regExp.toAutomaton(new DatatypesAutomatonProvider());
myRunAutomaton = new RunAutomaton(automaton, true);
//System.out.println("t = " + (System.currentTimeMillis() - t));
try {
myPattern = new Perl5Compiler().compile(regexp);
}
catch (MalformedPatternException e) {
throw new RuntimeException(e);
}
myMatcher = new Perl5Matcher();
}
public boolean matches(String name) {
@@ -402,7 +404,7 @@ public class NameUtil {
return false;
}
return myRunAutomaton.run(name);
return myMatcher.matches(name, myPattern);
}
private static String preparePattern(String pattern) {
+1 -11
View File
@@ -16,18 +16,8 @@
<orderEntry type="module" module-name="platform-resources-en" />
<orderEntry type="module" module-name="annotations" exported="" />
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../../lib/automaton.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MODULE_DIR$/../../lib/src/automaton-1.11.zip!/src" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="library" name="jna" level="project" />
<orderEntry type="library" name="OroMatcher" level="project" />
</component>
<component name="copyright">
<Base>
@@ -28,10 +28,12 @@ import com.intellij.openapi.vfs.newvfs.events.*;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -68,62 +70,50 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL
final FileAndDirsCollector dirtyFilesAndDirs = new FileAndDirsCollector();
// collect files and directories - sources of events
for (VFileEvent event : events) {
final String path = event.getPath();
final VirtualFile file = getFileForEvent(event);
if (file == null) { continue; }
if (event instanceof VFileDeleteEvent) {
final VirtualFile file = ((VFileDeleteEvent)event).getFile();
if (!file.isInLocalFileSystem()) { return; }
if (!file.isInLocalFileSystem()) { continue; }
dirtyFilesAndDirs.add(file);
} else if (event instanceof VFileMoveEvent) {
final VirtualFile file = ((VFileMoveEvent)event).getFile();
dirtyFilesAndDirs.addToFiles(file);
} else if (event instanceof VFilePropertyChangeEvent) {
final VirtualFile file = ((VFilePropertyChangeEvent)event).getFile();
} else if (event instanceof VFileMoveEvent || event instanceof VFilePropertyChangeEvent) {
dirtyFilesAndDirs.addToFiles(file);
}
}
// and notify VCSDirtyScopeManager
dirtyFilesAndDirs.markDirty();
}
@Override
public void after(List<? extends VFileEvent> events) {
final FileAndDirsCollector dirtyFilesAndDirs = new FileAndDirsCollector();
// collect files and directories - sources of events
for (VFileEvent event : events) {
if (event instanceof VFileContentChangeEvent) {
final VirtualFile file = ((VFileContentChangeEvent)event).getFile();
final VirtualFile file = getFileForEvent(event);
if (file == null) { continue; }
if (event instanceof VFileContentChangeEvent || event instanceof VFileCopyEvent || event instanceof VFileCreateEvent) {
dirtyFilesAndDirs.addToFiles(file);
} else if (event instanceof VFileCopyEvent) {
final VirtualFile file = ((VFileCopyEvent)event).getFile();
dirtyFilesAndDirs.addToFiles(file);
} else if (event instanceof VFileCreateEvent) {
final VFileCreateEvent ce = ((VFileCreateEvent)event);
final VirtualFile file = ce.getParent().findChild(ce.getChildName());
dirtyFilesAndDirs.addToFiles(file);
} else if (event instanceof VFileMoveEvent) {
dirtyFilesAndDirs.add(((VFileMoveEvent)event).getFile());
} else if (event instanceof VFilePropertyChangeEvent) {
final VFilePropertyChangeEvent pce = (VFilePropertyChangeEvent) event;
VirtualFile file = pce.getFile();
// if file was renamed, then mark dirty the file and its parent directory
if (pce.getPropertyName().equals(VirtualFile.PROP_NAME)) {
if (file.getParent() != null) {
file = file.getParent();
}
dirtyFilesAndDirs.add(file);
// if a file was renamed, then the file is dirty and its parent directory is dirty too;
// if a directory was renamed, all its children are recursively dirty, the parent dir is also dirty but not recursively.
dirtyFilesAndDirs.add(file); // the file is dirty recursively
dirtyFilesAndDirs.addToFiles(file.getParent()); // directory is dirty alone. if parent is null - is checked in the method
} else {
dirtyFilesAndDirs.addToFiles(file);
}
}
}
// and notify VCSDirtyScopeManager
dirtyFilesAndDirs.markDirty();
}
@Nullable
private VcsDirtyScopeManager getManager(final VirtualFile file) {
if (file == null) { return null; }
final Project project = myProjectLocator.guessProjectForFile(file);
if (project == null) { return null; }
return VcsDirtyScopeManager.getInstance(project);
private static VirtualFile getFileForEvent(VFileEvent event) {
return VcsUtil.getVirtualFile(event.getPath());
}
/**
@@ -144,28 +134,38 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL
* @param addToFiles If true, then add to dirty files even if it is a directory. Otherwise add to the proper set.
*/
private void add(VirtualFile file, boolean addToFiles) {
final VcsDirtyScopeManager manager = getManager(file);
if (manager == null) { return; }
Pair<HashSet<FilePath>, HashSet<FilePath>> filesAndDirs = map.get(manager);
if (filesAndDirs == null) {
filesAndDirs = Pair.create(new HashSet<FilePath>(), new HashSet<FilePath>());
map.put(manager, filesAndDirs);
}
if (file == null) { return; }
final boolean isDirectory = file.isDirectory();
// need to create FilePath explicitly without referring to VirtualFile because the path of VirtualFile may change
final FilePathImpl path = new FilePathImpl(new File(file.getPath()), isDirectory);
if (addToFiles || isDirectory) {
filesAndDirs.first.add(path);
} else {
filesAndDirs.second.add(path);
final Collection<VcsDirtyScopeManager> managers = getManagers(file);
for (VcsDirtyScopeManager manager : managers) {
Pair<HashSet<FilePath>, HashSet<FilePath>> filesAndDirs = map.get(manager);
if (filesAndDirs == null) {
filesAndDirs = Pair.create(new HashSet<FilePath>(), new HashSet<FilePath>());
map.put(manager, filesAndDirs);
}
if (addToFiles || !isDirectory) {
filesAndDirs.first.add(path);
} else {
filesAndDirs.second.add(path);
}
}
}
/**
* Adds files to the collection of files and directories - to the collection of directories (which are handled recursively).
*/
void add(VirtualFile file) {
add(file, false);
}
/**
* Adds to the collection of files. A file (even if it is a directory) is marked dirty alone (not recursively).
* Use this method, when you want directory not to be marked dirty recursively.
*/
void addToFiles(VirtualFile file) {
add(file, true);
}
@@ -180,4 +180,23 @@ public class VcsDirtyScopeVfsListener implements ApplicationComponent, BulkFileL
}
}
/**
* Returns all VcsDirtyScopeManagers which serve the given file.
* There may be none of them or there may be several (if a file is contained in several open projects, for instance),
* though usually there is one.
*/
@NotNull
private Collection<VcsDirtyScopeManager> getManagers(final VirtualFile file) {
final Collection<VcsDirtyScopeManager> result = new HashSet<VcsDirtyScopeManager>();
if (file == null) { return result; }
final Collection<Project> projects = myProjectLocator.getProjectsForFile(file);
for (Project project : projects) {
final VcsDirtyScopeManager manager = VcsDirtyScopeManager.getInstance(project);
if (manager != null) {
result.add(manager);
}
}
return result;
}
}
@@ -1768,6 +1768,7 @@ ignore.single.field.static.imports.option=Ignore single &field static imports
ignore.single.method.static.imports.option=Ignore single &method static imports
ignore.methods.with.boolean.return.type.option=Ignore methods with &Boolean return type
ignore.boolean.methods.in.an.interface.option=Ignore boolean methods in an @&interface
ignore.methods.overriding.super.method=Ignore methods &overriding a super method
ignored.io.resource.types=Ignored I/O resource types
choose.io.resource.type.to.ignore=Choose I/O resource type to ignore
ignore.accesses.from.the.same.class=ignore accesses from the same class
@@ -15,23 +15,26 @@
*/
package com.siyeh.ig.naming;
import com.intellij.codeInspection.ui.AddAction;
import com.intellij.codeInspection.ui.ListTable;
import com.intellij.codeInspection.ui.ListWrappingTableModel;
import com.intellij.codeInspection.ui.RemoveAction;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.RenameFix;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.ui.*;
import com.siyeh.ig.ui.CheckBox;
import com.siyeh.ig.ui.UiUtils;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -50,6 +53,9 @@ public class BooleanMethodNameMustStartWithQuestionInspection
@SuppressWarnings({"PublicField"})
public boolean ignoreInAnnotationInterface = true;
@SuppressWarnings({"PublicField"})
public boolean onlyWarnOnBaseMethods = true;
/** @noinspection PublicField*/
@NonNls public String questionString =
"is,can,has,should,could,will,shall,check,contains,equals,add," +
@@ -94,41 +100,28 @@ public class BooleanMethodNameMustStartWithQuestionInspection
new ListTable(new ListWrappingTableModel(questionList,
InspectionGadgetsBundle.message(
"boolean.method.name.must.start.with.question.table.column.name")));
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(table);
final JScrollPane scrollPane =
ScrollPaneFactory.createScrollPane(table);
final ActionToolbar toolbar =
UiUtils.createAddRemoveToolbar(table);
final GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridheight = 3;
constraints.fill = GridBagConstraints.HORIZONTAL;
panel.add(toolbar.getComponent(), constraints);
constraints.gridy = 1;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.fill = GridBagConstraints.BOTH;
panel.add(scrollPane, constraints);
final JButton addButton = new JButton(new AddAction(table));
constraints.gridx = 1;
constraints.gridheight = 1;
constraints.weightx = 0.0;
constraints.weighty = 0.0;
constraints.fill = GridBagConstraints.HORIZONTAL;
panel.add(addButton, constraints);
final JButton removeButton = new JButton(new RemoveAction(table));
constraints.gridy = 1;
panel.add(removeButton, constraints);
final BlankFiller filler = new BlankFiller();
constraints.gridy = 2;
constraints.weighty = 1.0;
panel.add(filler, constraints);
final CheckBox checkBox1 =
new CheckBox(InspectionGadgetsBundle.message(
"ignore.methods.with.boolean.return.type.option"),
this, "ignoreBooleanMethods");
constraints.gridy = 3;
constraints.gridx = 0;
constraints.gridwidth = 2;
constraints.gridy = 2;
constraints.weighty = 0.0;
panel.add(checkBox1, constraints);
@@ -136,8 +129,15 @@ public class BooleanMethodNameMustStartWithQuestionInspection
new CheckBox(InspectionGadgetsBundle.message(
"ignore.boolean.methods.in.an.interface.option"),
this, "ignoreInAnnotationInterface");
constraints.gridy = 4;
constraints.gridy = 3;
panel.add(checkBox2, constraints);
final CheckBox checkBox3 =
new CheckBox(InspectionGadgetsBundle.message(
"ignore.methods.overriding.super.method"),
this, "onlyWarnOnBaseMethods");
constraints.gridy = 4;
panel.add(checkBox3, constraints);
return panel;
}
@@ -182,7 +182,13 @@ public class BooleanMethodNameMustStartWithQuestionInspection
return;
}
}
if(LibraryUtil.isOverrideOfLibraryMethod(method)){
if (onlyWarnOnBaseMethods) {
final Query<MethodSignatureBackedByPsiMethod> superSearch =
SuperMethodsSearch.search(method, null, true, false);
if (superSearch.findFirst() != null) {
return;
}
} else if (LibraryUtil.isOverrideOfLibraryMethod(method)) {
return;
}
registerMethodError(method);
@@ -15,22 +15,25 @@
*/
package com.siyeh.ig.naming;
import com.intellij.codeInspection.ui.AddAction;
import com.intellij.codeInspection.ui.ListTable;
import com.intellij.codeInspection.ui.ListWrappingTableModel;
import com.intellij.codeInspection.ui.RemoveAction;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.RenameFix;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.ui.*;
import com.siyeh.ig.ui.CheckBox;
import com.siyeh.ig.ui.UiUtils;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -51,6 +54,9 @@ public class NonBooleanMethodNameMayNotStartWithQuestionInspection
@SuppressWarnings({"PublicField"})
public boolean ignoreBooleanMethods = false;
@SuppressWarnings({"PublicField"})
public boolean onlyWarnOnBaseMethods = true;
List<String> questionList = new ArrayList(32);
public NonBooleanMethodNameMayNotStartWithQuestionInspection(){
@@ -90,43 +96,36 @@ public class NonBooleanMethodNameMayNotStartWithQuestionInspection
new ListTable(new ListWrappingTableModel(questionList,
InspectionGadgetsBundle.message(
"boolean.method.name.must.start.with.question.table.column.name")));
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(table);
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(table);
final ActionToolbar toolbar =
UiUtils.createAddRemoveToolbar(table);
final GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridheight = 3;
constraints.fill = GridBagConstraints.HORIZONTAL;
panel.add(toolbar.getComponent(), constraints);
constraints.gridy = 1;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.fill = GridBagConstraints.BOTH;
panel.add(scrollPane, constraints);
final JButton addButton = new JButton(new AddAction(table));
constraints.gridx = 1;
constraints.gridheight = 1;
constraints.weightx = 0.0;
constraints.weighty = 0.0;
constraints.fill = GridBagConstraints.HORIZONTAL;
panel.add(addButton, constraints);
final JButton removeButton = new JButton(new RemoveAction(table));
constraints.gridy = 1;
panel.add(removeButton, constraints);
final BlankFiller filler = new BlankFiller();
constraints.gridy = 2;
constraints.weighty = 1.0;
panel.add(filler, constraints);
final CheckBox checkBox =
final CheckBox checkBox1 =
new CheckBox(InspectionGadgetsBundle.message(
"ignore.methods.with.boolean.return.type.option"),
this, "ignoreBooleanMethods");
constraints.gridy = 3;
constraints.gridx = 0;
constraints.gridwidth = 2;
constraints.gridy = 2;
constraints.weighty = 0.0;
panel.add(checkBox, constraints);
panel.add(checkBox1, constraints);
final CheckBox checkBox2 =
new CheckBox(InspectionGadgetsBundle.message(
"ignore.methods.overriding.super.method"),
this, "onlyWarnOnBaseMethods");
constraints.gridy = 3;
panel.add(checkBox2, constraints);
return panel;
}
@@ -173,8 +172,16 @@ public class NonBooleanMethodNameMayNotStartWithQuestionInspection
}
}
}
if(!startsWithQuestionWord ||
LibraryUtil.isOverrideOfLibraryMethod(method)){
if(!startsWithQuestionWord){
return;
}
if (onlyWarnOnBaseMethods) {
final Query<MethodSignatureBackedByPsiMethod> superSearch =
SuperMethodsSearch.search(method, null, true, false);
if (superSearch.findFirst() != null) {
return;
}
} else if (LibraryUtil.isOverrideOfLibraryMethod(method)) {
return;
}
registerMethodError(method);
@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.siyeh.ig.naming.QuestionableNameInspection.Form">
<grid id="f9915" binding="contentPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="4" vgap="4">
<margin top="4" left="4" bottom="4" right="4"/>
<constraints>
<xy x="94" y="35" width="282" height="158"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<scrollpane class="com.intellij.ui.components.JBScrollPane" id="14807">
<constraints>
<grid row="0" column="0" row-span="3" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="47930" class="com.intellij.codeInspection.ui.ListTable" binding="table" custom-create="true">
<constraints/>
<properties/>
</component>
</children>
</scrollpane>
<component id="52926" class="javax.swing.JButton" binding="addButton">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<margin top="3" left="8" bottom="3" right="8"/>
<text resource-bundle="com/siyeh/InspectionGadgetsBundle" key="button.add"/>
</properties>
</component>
<component id="f6174" class="javax.swing.JButton" binding="removeButton">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<margin top="3" left="8" bottom="3" right="8"/>
<text resource-bundle="com/siyeh/InspectionGadgetsBundle" key="button.remove"/>
</properties>
</component>
<vspacer id="f3a31">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,25 +15,27 @@
*/
package com.siyeh.ig.naming;
import com.intellij.codeInspection.ui.RemoveAction;
import com.intellij.codeInspection.ui.ListTable;
import com.intellij.codeInspection.ui.ListWrappingTableModel;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiVariable;
import com.intellij.ui.ScrollPaneFactory;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.RenameFix;
import com.intellij.codeInspection.ui.AddAction;
import com.intellij.codeInspection.ui.ListTable;
import com.intellij.codeInspection.ui.ListWrappingTableModel;
import com.siyeh.ig.ui.UiUtils;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -54,41 +56,69 @@ public class QuestionableNameInspection extends BaseInspection {
parseString(nameString, nameList);
}
@Override
@NotNull
public String getDisplayName(){
return InspectionGadgetsBundle.message(
"questionable.name.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos){
return InspectionGadgetsBundle.message(
"questionable.name.problem.descriptor");
}
@Override
public void readSettings(Element element) throws InvalidDataException{
super.readSettings(element);
parseString(nameString, nameList);
}
@Override
public void writeSettings(Element element) throws WriteExternalException{
nameString = formatString(nameList);
super.writeSettings(element);
}
@Override
public JComponent createOptionsPanel(){
final Form form = new Form();
return form.getContentPanel();
final JPanel panel = new JPanel(new GridBagLayout());
final ListTable table = new ListTable(new ListWrappingTableModel(
nameList, InspectionGadgetsBundle.message(
"questionable.name.column.title")));
final JScrollPane scrollPane =
ScrollPaneFactory.createScrollPane(table);
final ActionToolbar toolbar =
UiUtils.createAddRemoveToolbar(table);
final GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
panel.add(toolbar.getComponent(), constraints);
constraints.gridy = 1;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.fill = GridBagConstraints.BOTH;
panel.add(scrollPane, constraints);
return panel;
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos){
return new RenameFix();
}
@Override
protected boolean buildQuickFixesOnlyForOnTheFlyErrors(){
return true;
}
@Override
public BaseInspectionVisitor buildVisitor(){
return new QuestionableNameVisitor();
}
@@ -118,28 +148,4 @@ public class QuestionableNameInspection extends BaseInspection {
}
}
}
private class Form{
JPanel contentPanel;
JButton addButton;
JButton removeButton;
ListTable table;
Form(){
super();
addButton.setAction(new AddAction(table));
removeButton.setAction(new RemoveAction(table));
}
private void createUIComponents() {
table = new ListTable(new ListWrappingTableModel(
nameList, InspectionGadgetsBundle.message(
"questionable.name.column.title")));
}
public JComponent getContentPanel(){
return contentPanel;
}
}
}
@@ -0,0 +1,212 @@
/*
* Copyright 2000-2010 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.tests;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.VcsAppendableDirtyScope;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeImpl;
import com.intellij.openapi.vcs.changes.pending.MockChangeListManagerGate;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.vcs.MockChangelistBuilder;
import com.intellij.vcsUtil.VcsUtil;
import git4idea.GitVcs;
import git4idea.changes.GitChangeProvider;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.intellij.openapi.vcs.FileStatus.ADDED;
import static com.intellij.openapi.vcs.FileStatus.MODIFIED;
import static com.intellij.openapi.vcs.FileStatus.DELETED;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
/**
* Tests GitChangeProvider functionality. Scenario is the same for all tests:
* 1. Modifies files on disk (creates, edits, deletes, etc.)
* 2. Manually adds them to a dirty scope (better to use VcsDirtyScopeManagerImpl, but it's too asynchronous - couldn't overcome this for now.
* 3. Calls ChangeProvider.getChanges() and checks that the changes are there.
* TODO: change VirtualFile to FilePath or path declared by String - and add tests on move etc. Otherwise VirtualFile is not fuctional for move and harder to test deletes.
* TODO: there is almost nothing special about git. Expand to all version controls. But beware that tests should be modified on VCs which track directories.
* @author Kirill Likhodedov
*/
public class GitChangeProviderTest extends GitTestCase {
private GitChangeProvider myChangeProvider;
private VcsAppendableDirtyScope myDirtyScope;
private Map<String, VirtualFile> myFiles;
private VirtualFile afile;
@BeforeMethod
@Override
protected void setUp() throws Exception {
super.setUp();
myChangeProvider = (GitChangeProvider) GitVcs.getInstance(myProject).getChangeProvider();
myDirtyScope = new VcsDirtyScopeImpl(GitVcs.getInstance(myProject), myProject);
myFiles = createFileStructure("a.txt", "b.txt", "dir/c.txt", "dir/subdir/d.txt");
afile = myFiles.get("a.txt"); // the file is commonly used, so save it in a field.
myRepo.commit();
}
@Test
public void testCreateFile() throws Exception {
VirtualFile bfile = myRepo.createFile("new.txt");
assertChanges(bfile, ADDED);
}
@Test
public void testCreateFileInDir() throws Exception {
VirtualFile dir = createDirInCommand(myRepo.getDir(), "newdir");
VirtualFile bfile = createFileInCommand(dir, "new.txt", "initial b");
assertChanges(new VirtualFile[] {bfile, dir}, new FileStatus[] { ADDED, null} );
}
@Test
public void testEditFile() throws Exception {
editFileInCommand(afile, "new content");
assertChanges(afile, MODIFIED);
}
@Test
public void testDeleteFile() throws Exception {
deleteFileInCommand(afile);
assertChanges(afile, DELETED);
}
@Test
public void testDeleteDirRecursively() throws Exception {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override public void run() {
FileUtil.delete(new File(myRepo.getDir().getPath(), "dir"));
}
});
assertChanges(new VirtualFile[] { myFiles.get("dir/c.txt"), myFiles.get("dir/subdir/d.txt") }, new FileStatus[] { DELETED, DELETED });
}
@Test
public void testSimultaneousOperationsOnMultipleFiles() throws Exception {
VirtualFile dfile = myFiles.get("dir/subdir/d.txt");
VirtualFile cfile = myFiles.get("dir/c.txt");
editFileInCommand(afile, "new content");
editFileInCommand(cfile, "new content");
deleteFileInCommand(dfile);
VirtualFile newfile = createFileInCommand("newfile.txt", "new content");
assertChanges(new VirtualFile[] {afile, cfile, dfile, newfile}, new FileStatus[] {MODIFIED, MODIFIED, DELETED, ADDED});
}
/**
* Checks that the given files have respective statuses in the change list retrieved from myChangesProvider.
* Pass null in the fileStatuses array to indicate that proper file has not changed.
*/
private void assertChanges(VirtualFile[] virtualFiles, FileStatus[] fileStatuses) throws VcsException {
Map<VirtualFile, Change> result = getChanges(virtualFiles);
for (int i = 0; i < virtualFiles.length; i++) {
VirtualFile vf = virtualFiles[i];
FileStatus status = fileStatuses[i];
if (status == null) {
assertFalse(result.containsKey(vf), "File [" + vf + " shouldn't be in the change list, but it was.");
continue;
}
assertTrue(result.containsKey(vf), "File [" + vf + "] didn't change. Changes: " + result);
assertEquals(result.get(vf).getFileStatus(), status, "File statuses don't match for file [" + vf + "]");
}
}
private void assertChanges(VirtualFile virtualFile, FileStatus fileStatus) throws VcsException {
assertChanges(new VirtualFile[] { virtualFile }, new FileStatus[] { fileStatus });
}
/**
* Marks the given files dirty in myDirtyScope, gets changes from myChangeProvider and groups the changes in the map.
* Assumes that only one change for a file happened.
*/
private Map<VirtualFile, Change> getChanges(VirtualFile... changedFiles) throws VcsException {
// populate dirty scope
for (VirtualFile vf : changedFiles) {
myDirtyScope.addDirtyFile(new FilePathImpl(vf));
}
// get changes
MockChangelistBuilder builder = new MockChangelistBuilder();
myChangeProvider.getChanges(myDirtyScope, builder, new EmptyProgressIndicator(), new MockChangeListManagerGate(ChangeListManager.getInstance(myProject)));
List<Change> changes = builder.getChanges();
// get changes for files
Map<VirtualFile, Change> result = new HashMap<VirtualFile, Change>();
for (Change change : changes) {
VirtualFile file = change.getVirtualFile();
if (file == null) { // if a file was deleted, just find the reference in the original list of files and use it.
String path = change.getBeforeRevision().getFile().getPath();
for (VirtualFile vf : changedFiles) {
if (vf.getPath().equals(path)) {
file = vf;
break;
}
}
}
result.put(file, change);
}
return result;
}
/**
* <p>Creates file structure for given paths. Path element should be a relative (from project root)
* path to a file or a directory. All intermediate paths will be created if needed.
* To create a dir without creating a file pass "dir/" as a parameter.</p>
* <p>Usage example:
* <code>createFileStructure("a.txt", "b.txt", "dir/c.txt", "dir/subdir/d.txt", "anotherdir/");</code></p>
* <p>This will create files a.txt and b.txt in the project dir, create directories dir, dir/subdir and anotherdir,
* and create file c.txt in dir and d.txt in dir/subdir.</p>
* <p>Note: use forward slash to denote directories, even if it is backslash that separates dirs in your system.</p>
* <p>All files are populated with "initial content" string.</p>
*/
private Map<String, VirtualFile> createFileStructure(String... paths) {
Map<String, VirtualFile> result = new HashMap<String, VirtualFile>();
for (String path : paths) {
String[] pathElements = path.split("/");
boolean lastIsDir = path.endsWith("/");
VirtualFile currentParent = myRepo.getDir();
for (int i = 0; i < pathElements.length-1; i++) {
currentParent = createDirInCommand(currentParent, pathElements[i]);
}
String lastElement = pathElements[pathElements.length-1];
currentParent = lastIsDir ? createDirInCommand(currentParent, lastElement) : createFileInCommand(currentParent, lastElement, "initial content");
result.put(path, currentParent);
}
return result;
}
}
@@ -23,7 +23,6 @@ import com.intellij.openapi.vcs.VcsShowConfirmationOption;
import com.intellij.testFramework.AbstractVcsTestCase;
import git4idea.GitVcs;
import org.jetbrains.annotations.Nullable;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import java.io.File;
@@ -16,6 +16,9 @@
package git4idea.tests;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.AbstractVcsTestCase;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
@@ -24,6 +27,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* Representation of a Git repository for tests purposes.
@@ -87,56 +91,83 @@ public class GitTestRepository {
}
/**
* Natively executes the given mercurial command.
* Natively executes the given mercurial command inside write or read action.
* @param writeAction If true, the command will be executed in a write action, otherwise - inside a read action.
* @param commandWithParameters Mercurial command with parameters. E.g. ["status", "-a"]
*/
public ProcessOutput execute(String... commandWithParameters) throws IOException {
return myTest.executeCommand(new File(myDirFixture.getTempDirPath()), commandWithParameters);
public ProcessOutput execute(boolean writeAction, final String... commandWithParameters) throws IOException {
final AtomicReference<ProcessOutput> result = new AtomicReference<ProcessOutput>();
final Runnable action = new Runnable() {
@Override public void run() {
try {
result.set(myTest.executeCommand(new File(myDirFixture.getTempDirPath()), commandWithParameters));
} catch (IOException e) {
result.set(null);
}
}
};
if (ApplicationManager.getApplication() == null) { // application may be not initialized yet. OK to just run the action then.
action.run();
return result.get();
}
if (writeAction) {
ApplicationManager.getApplication().runWriteAction(action);
} else {
ApplicationManager.getApplication().runReadAction(action);
}
return result.get();
}
public void add() throws IOException {
execute("add", ".");
execute(true, "add", ".");
}
public void commit(@Nullable String commitMessage) throws IOException {
if (commitMessage == null) {
commitMessage = "Sample commit message";
}
execute("commit", "-m", commitMessage);
execute(true, "commit", "-m", commitMessage);
}
/**
* Commit with a sample commit message. Use this when commit message doesn't matter to your test.
*/
public void commit() throws IOException {
commit(null);
}
public void config(String... parameters) throws IOException {
String[] pars = new String[parameters.length+1];
pars[0] = "config";
System.arraycopy(parameters, 0, pars, 1, parameters.length);
execute(pars);
execute(true, pars);
}
public ProcessOutput log(String... parameters) throws IOException {
String[] pars = new String[parameters.length+1];
pars[0] = "log";
System.arraycopy(parameters, 0, pars, 1, parameters.length);
return execute(pars);
return execute(false, pars);
}
public void merge() throws IOException {
execute("merge");
execute(true, "merge");
}
public void mv(VirtualFile file, String newPath) throws IOException {
execute("mv", file.getPath(), newPath);
execute(true, "mv", file.getPath(), newPath);
}
public void pull() throws IOException {
execute("pull");
execute(true, "pull");
}
public void push() throws IOException {
execute("push");
execute(true, "push");
}
public void update() throws IOException {
execute("update");
execute(true, "update");
}
/**
@@ -37,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.MaybeReturnInstruction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SuppressWarnings({"OverlyComplexClass"})
@@ -442,17 +443,18 @@ public class ControlFlowUtils {
return false;
}
public static List<GrStatement> collectReturns(PsiElement element) {
public static List<GrStatement> collectReturns(@Nullable PsiElement element) {
return collectReturns(element, element instanceof GrCodeBlock);
}
public static List<GrStatement> collectReturns(PsiElement element, final boolean allExitPoints) {
public static List<GrStatement> collectReturns(@Nullable PsiElement element, final boolean allExitPoints) {
if (element == null) return Collections.emptyList();
final Instruction[] flow;
if (element instanceof GrCodeBlock) {
flow = ((GrCodeBlock)element).getControlFlow();
}
else {
flow = new ControlFlowBuilder(element.getProject()).buildControlFlow(
(GroovyPsiElement)element, null, null);
flow = new ControlFlowBuilder(element.getProject()).buildControlFlow((GroovyPsiElement)element, null, null);
}
boolean[] visited = new boolean[flow.length];
final List<GrStatement> res = new ArrayList<GrStatement>();
@@ -2,6 +2,7 @@ package org.jetbrains.plugins.groovy.dsl;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import groovy.lang.Closure;
import org.jetbrains.annotations.Nullable;
@@ -25,10 +26,9 @@ public class CustomMembersGenerator implements GdslMembersHolderConsumer {
private final GroovyClassDescriptor myDescriptor;
private final String myQualifiedName;
public CustomMembersGenerator(GroovyClassDescriptor descriptor) {
public CustomMembersGenerator(GroovyClassDescriptor descriptor, PsiType type) {
myDescriptor = descriptor;
myProject = descriptor.getProject();
final PsiType type = descriptor.getPsiType();
if (type instanceof PsiClassType) {
final PsiClass psiClass = ((PsiClassType)type).resolve();
if (psiClass != null) {
@@ -72,9 +72,13 @@ public class CustomMembersGenerator implements GdslMembersHolderConsumer {
@Nullable
public CustomMembersHolder getMembersHolder() {
// Add non-code members holder
if (!myMethods.isEmpty()) {
addMemberHolder(NonCodeMembersHolder.generateMembers(myMethods, myDescriptor.getPlaceFile()));
addMemberHolder(new CustomMembersHolder() {
@Override
public boolean processMembers(GroovyClassDescriptor descriptor, PsiScopeProcessor processor, ResolveState state) {
return NonCodeMembersHolder.generateMembers(myMethods, descriptor.getPlaceFile()).processMembers(descriptor, processor, state);
}
});
}
return myDepot;
}
@@ -1,8 +1,7 @@
package org.jetbrains.plugins.groovy.dsl;
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiType
import org.jetbrains.plugins.groovy.dsl.dsltop.GdslMembersProvider
/**
@@ -10,8 +9,8 @@ import org.jetbrains.plugins.groovy.dsl.dsltop.GdslMembersProvider
*/
public class ExtensibleCustomMembersGenerator extends CustomMembersGenerator {
public ExtensibleCustomMembersGenerator(GroovyClassDescriptor descriptor) {
super(descriptor)
public ExtensibleCustomMembersGenerator(GroovyClassDescriptor descriptor, PsiType type) {
super(descriptor, type)
}
def methodMissing(String name, args) {
@@ -0,0 +1,67 @@
package org.jetbrains.plugins.groovy.dsl;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.dsl.holders.CustomMembersHolder;
import java.util.Map;
/**
* @author peter
*/
public class FactorTree {
private static final Object ourHolderKey = new Object();
private final Map myCache = new ConcurrentHashMap();
public void cache(GroovyClassDescriptor descriptor, CustomMembersHolder holder) {
Map current = myCache;
for (Factor factor : descriptor.affectingFactors) {
Object key;
switch (factor) {
case placeElement: key = descriptor.getPlace(); break;
//case placeFile: key = descriptor.getPlaceFile(); break;
case qualifierType: key = descriptor.getPsiType().getCanonicalText(); break;
default: throw new IllegalStateException("Unknown variant: "+ factor);
}
Map next = (Map)current.get(key);
if (next == null) current.put(key, next = new ConcurrentHashMap());
current = next;
}
current.put(ourHolderKey, holder);
}
@Nullable
public CustomMembersHolder retrieve(PsiElement place, String qualifierType) {
return retrieveImpl(place, qualifierType, myCache);
}
@Nullable
private static CustomMembersHolder retrieveImpl(@NotNull PsiElement place,
@NotNull String qualifierType, @Nullable Map current) {
if (current == null) return null;
CustomMembersHolder result;
result = (CustomMembersHolder)current.get(ourHolderKey);
if (result != null) return result;
result = retrieveImpl(place, qualifierType, (Map)current.get(qualifierType));
if (result != null) return result;
/*
result = retrieveImpl(place, placeFile, qualifierType, (Map)current.get(placeFile));
if (result != null) return result;
*/
return retrieveImpl(place, qualifierType, (Map)current.get(place));
}
}
enum Factor {
qualifierType, placeElement//, placeFile
}
@@ -26,6 +26,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -44,13 +46,13 @@ public class GroovyClassDescriptor {
private final PsiType myPsiType;
private final PsiElement myPlace;
private final PsiFile myFile;
private final boolean myPlaceDependent;
private boolean myPlaceElementAccessed;
public GroovyClassDescriptor(@NotNull PsiType psiType, GroovyPsiElement place, boolean placeDependent, final PsiFile placeFile) {
@SuppressWarnings({"SetReplaceableByEnumSet"}) //order is important
final Set<Factor> affectingFactors = new LinkedHashSet<Factor>();
public GroovyClassDescriptor(@NotNull PsiType psiType, GroovyPsiElement place, final PsiFile placeFile) {
myPsiType = psiType;
myPlace = place;
myPlaceDependent = placeDependent;
myFile = placeFile;
}
@@ -59,58 +61,32 @@ public class GroovyClassDescriptor {
}
public GlobalSearchScope getResolveScope() {
//affectingFactors.add(Factor.placeFile);
return myPlace.getResolveScope();
}
@Nullable
public String getTypeText() {
return myPsiType.getCanonicalText();
return getPsiType().getCanonicalText();
}
public boolean isInheritor(String qname) {
return InheritanceUtil.isInheritor(myPsiType, qname);
return InheritanceUtil.isInheritor(getPsiType(), qname);
}
public PsiElement getPlace() {
myPlaceElementAccessed = true;
affectingFactors.add(Factor.placeElement);
return myPlace;
}
public PsiType getPsiType() {
affectingFactors.add(Factor.qualifierType);
return myPsiType;
}
public PsiFile getPlaceFile() {
//affectingFactors.add(Factor.placeFile);
return myFile;
}
public boolean placeAccessed() {
return myPlaceElementAccessed;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GroovyClassDescriptor that = (GroovyClassDescriptor)o;
if (!myPsiType.isValid() || !that.myPsiType.isValid()) return false;
if (!myPsiType.equals(that.myPsiType)) return false;
if (myPlaceDependent) {
return myPlace.equals(that.myPlace);
}
return myFile.equals(that.myFile);
}
@Override
public int hashCode() {
int result = myPsiType.hashCode() * 31 + myFile.hashCode();
if (myPlaceDependent) {
return result * 31 + myPlace.hashCode();
}
return result;
}
}
@@ -23,10 +23,6 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.ClassContextFilter;
import org.jetbrains.plugins.groovy.dsl.toplevel.ContextFilter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author peter
*/
@@ -35,18 +31,16 @@ public class GroovyDslScript {
public final Project project;
public final VirtualFile file;
public final GroovyDslExecutor executor;
private final CachedValue<Pair<ConcurrentMap<String, Boolean>, ConcurrentMap<GroovyClassDescriptor, CustomMembersHolder>>> myMaps;
private final CachedValue<FactorTree> myMaps;
public GroovyDslScript(final Project project, VirtualFile file, GroovyDslExecutor executor) {
this.project = project;
this.file = file;
this.executor = executor;
myMaps = CachedValuesManager.getManager(project).createCachedValue(new CachedValueProvider<Pair<ConcurrentMap<String, Boolean>, ConcurrentMap<GroovyClassDescriptor, CustomMembersHolder>>>() {
myMaps = CachedValuesManager.getManager(project).createCachedValue(new CachedValueProvider<FactorTree>() {
@Override
public Result<Pair<ConcurrentMap<String, Boolean>, ConcurrentMap<GroovyClassDescriptor, CustomMembersHolder>>> compute() {
ConcurrentMap<String, Boolean> specificities = new ConcurrentHashMap<String, Boolean>();
ConcurrentMap<GroovyClassDescriptor, CustomMembersHolder> holders = new ConcurrentHashMap<GroovyClassDescriptor, CustomMembersHolder>();
return Result.create(Pair.create(specificities, holders), PsiModificationTracker.MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
public Result<FactorTree> compute() {
return Result.create(new FactorTree(), PsiModificationTracker.MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
}
}, false);
}
@@ -57,41 +51,26 @@ public class GroovyDslScript {
final GroovyPsiElement place,
final PsiFile placeFile,
final String qname) {
final Pair<ConcurrentMap<String, Boolean>, ConcurrentMap<GroovyClassDescriptor, CustomMembersHolder>> maps = myMaps.getValue();
Map<String, Boolean> specificities = maps.first;
boolean firstTime = !specificities.containsKey(qname);
final boolean placeDependent = firstTime || specificities.get(qname);
GroovyClassDescriptor descriptor = new GroovyClassDescriptor(psiType, place, placeDependent, placeFile);
final ConcurrentMap<GroovyClassDescriptor, CustomMembersHolder> members = maps.second;
CustomMembersHolder holder = members.get(descriptor);
final FactorTree cache = myMaps.getValue();
CustomMembersHolder holder = cache.retrieve(place, qname);
GroovyClassDescriptor descriptor = new GroovyClassDescriptor(psiType, place, placeFile);
if (holder == null) {
holder = addGdslMembers(descriptor, qname);
if (firstTime) {
final boolean placeAccessed = descriptor.placeAccessed();
specificities.put(qname, placeAccessed);
final GroovyClassDescriptor newDescriptor = new GroovyClassDescriptor(psiType, place, placeAccessed, placeFile);
members.putIfAbsent(newDescriptor, holder);
}
else {
members.putIfAbsent(descriptor, holder);
}
holder = addGdslMembers(descriptor, qname, psiType);
cache.cache(descriptor, holder);
}
return holder.processMembers(descriptor, processor, ResolveState.initial());
}
private CustomMembersHolder addGdslMembers(GroovyClassDescriptor descriptor, String qname) {
private CustomMembersHolder addGdslMembers(GroovyClassDescriptor descriptor, String qname, final PsiType psiType) {
final ProcessingContext ctx = new ProcessingContext();
ctx.put(ClassContextFilter.getClassKey(qname), descriptor.getPsiType());
ctx.put(ClassContextFilter.getClassKey(qname), psiType);
try {
if (!isApplicable(executor, descriptor, ctx)) {
return CustomMembersHolder.EMPTY;
}
final ExtensibleCustomMembersGenerator generator = new ExtensibleCustomMembersGenerator(descriptor);
final ExtensibleCustomMembersGenerator generator = new ExtensibleCustomMembersGenerator(descriptor, psiType);
executor.processVariants(descriptor, generator, ctx);
return generator.getMembersHolder();
}
@@ -1,74 +0,0 @@
/*
* Copyright 2000-2010 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.dsl.toplevel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.Function;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author Maxim.Medvedev
*/
public class CategoryMethodProvider {
private static final Key<CachedValue<MultiMap<String, PsiMethod>>> METHOD_KEY = Key.create("Category methods");
private CategoryMethodProvider() {
}
public static List<PsiMethod> provideMethods(@NotNull PsiType psiType,
final Project project,
String className,
final GlobalSearchScope scope,
final Function<PsiMethod, PsiMethod> converter) {
final PsiClass categoryClass = JavaPsiFacade.getInstance(project).findClass(className, scope);
if (categoryClass == null) return Collections.emptyList();
final MultiMap<String, PsiMethod> map = CachedValuesManager.getManager(project)
.getCachedValue(categoryClass, METHOD_KEY, new CachedValueProvider<MultiMap<String, PsiMethod>>() {
@Override
public Result<MultiMap<String, PsiMethod>> compute() {
MultiMap<String, PsiMethod> map = new MultiMap<String, PsiMethod>();
PsiManager manager = PsiManager.getInstance(project);
for (PsiMethod m : categoryClass.getMethods()) {
final PsiParameter[] params = m.getParameterList().getParameters();
if (params.length == 0) continue;
final PsiType parameterType = TypesUtil.boxPrimitiveType(params[0].getType(), manager, scope);
PsiType targetType = TypeConversionUtil.erasure(parameterType);
map.putValue(targetType.getCanonicalText(), converter.fun(m));
}
return Result.create(map, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
}
}, false);
Set<String> superTypes = ResolveUtil.getAllSuperTypes(psiType, project).keySet();
List<PsiMethod> result = new ArrayList<PsiMethod>();
for (String superType : superTypes) {
result.addAll(map.get(superType));
}
return result;
}
}
@@ -24,11 +24,12 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.*;
import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
import com.intellij.ui.components.JBList;
@@ -64,6 +65,7 @@ import java.util.*;
*/
public class CreateParameterForFieldIntention extends Intention {
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.intentions.control.CreateParameterForFieldIntention");
private static final Key<CachedValue<List<GrField>>> FIELD_CANDIDATES = Key.create("Fields.candidates");
@NotNull
@Override
@@ -125,7 +127,6 @@ public class CreateParameterForFieldIntention extends Intention {
}, GroovyIntentionsBundle.message("create.parameter.for.field.intention.name"), null);
}
}).createPopup().showInBestPositionFor(editor);
}
private static void performForConstructor(PsiElement element, final Project project, Editor editor, List<GrField> candidates) {
@@ -243,12 +244,11 @@ public class CreateParameterForFieldIntention extends Intention {
final PsiClass clazz = constructor.getContainingClass();
if (!(clazz instanceof GrTypeDefinition)) return null;
return findCandidates(constructor, (GrTypeDefinition)clazz);
return findCandidatesCached(constructor, (GrTypeDefinition)clazz);
}
private static List<GrField> findCandidates(GrMethod constructor, final GrTypeDefinition clazz) {
final List<GrField> usedFields = new ArrayList<GrField>();
//ContainerUtil.addAll(fields, clazz.getFields());
final GrOpenBlock block = constructor.getBlock();
LOG.assertTrue(block != null);
@@ -290,6 +290,21 @@ public class CreateParameterForFieldIntention extends Intention {
return fields;
}
private static List<GrField> findCandidatesCached(final GrMethod constructor, final GrTypeDefinition clazz) {
final CachedValue<List<GrField>> value = constructor.getUserData(FIELD_CANDIDATES);
if (value != null && value.getValue() != null) return value.getValue();
final CachedValue<List<GrField>> cachedValue =
CachedValuesManager.getManager(constructor.getProject()).createCachedValue(new CachedValueProvider<List<GrField>>() {
@Override
public Result<List<GrField>> compute() {
return Result.create(findCandidates(constructor, clazz), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
}, false);
constructor.putUserData(FIELD_CANDIDATES, cachedValue);
return cachedValue.getValue();
}
@Nullable
private static List<GrMethod> findConstructorCandidates(PsiElement element) {
final GrField field = PsiTreeUtil.getParentOfType(element, GrField.class);
@@ -302,7 +317,7 @@ public class CreateParameterForFieldIntention extends Intention {
final PsiMethod[] constructors = psiClass.getConstructors();
final PsiManager manager = field.getManager();
for (PsiMethod constructor : constructors) {
final List<GrField> fields = findCandidates(((GrMethod)constructor), psiClass);
final List<GrField> fields = findCandidatesCached(((GrMethod)constructor), psiClass);
if (ContainerUtil.find(fields, new Condition<GrField>() {
@Override
public boolean value(GrField grField) {
@@ -15,16 +15,22 @@
*/
package org.jetbrains.plugins.groovy.lang.resolve;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.ResolveState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.VolatileNotNullLazyValue;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.Function;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.dsl.GdslMembersHolderConsumer;
import org.jetbrains.plugins.groovy.dsl.GroovyClassDescriptor;
import org.jetbrains.plugins.groovy.dsl.dsltop.GdslMembersProvider;
import org.jetbrains.plugins.groovy.dsl.holders.CustomMembersHolder;
import org.jetbrains.plugins.groovy.dsl.toplevel.CategoryMethodProvider;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl;
/**
@@ -32,6 +38,8 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl;
*/
@SuppressWarnings({"MethodMayBeStatic"})
public class GdkMethodDslProvider implements GdslMembersProvider {
private static final Key<CachedValue<MultiMap<String, PsiMethod>>> METHOD_KEY = Key.create("Category methods");
public void category(String className, GdslMembersHolderConsumer consumer) {
processCategoryMethods(className, consumer, new Function<PsiMethod, PsiMethod>() {
public PsiMethod fun(PsiMethod m) {
@@ -53,19 +61,60 @@ public class GdkMethodDslProvider implements GdslMembersProvider {
}
public static void processCategoryMethods(final String className, final GdslMembersHolderConsumer consumer, final Function<PsiMethod, PsiMethod> converter) {
final GlobalSearchScope scope = consumer.getResolveScope();
final PsiClass categoryClass = JavaPsiFacade.getInstance(consumer.getProject()).findClass(className, scope);
if (categoryClass == null) {
return;
}
final VolatileNotNullLazyValue<MultiMap<String, PsiMethod>> methodsMap = new VolatileNotNullLazyValue<MultiMap<String, PsiMethod>>() {
@NotNull
@Override
protected MultiMap<String, PsiMethod> compute() {
return retrieveMethodMap(consumer.getProject(), scope, converter, categoryClass);
}
};
consumer.addMemberHolder(new CustomMembersHolder() {
@Override
public boolean processMembers(GroovyClassDescriptor descriptor, PsiScopeProcessor processor, ResolveState state) {
final PsiType psiType = descriptor.getPsiType();
if (psiType == null) return true;
for (PsiMethod method : CategoryMethodProvider.provideMethods(psiType, descriptor.getProject(), className, descriptor.getResolveScope(), converter)) {
if (!processor.execute(method, state)) {
return false;
final MultiMap<String, PsiMethod> map = methodsMap.getValue();
for (String superType : ResolveUtil.getAllSuperTypes(psiType, descriptor.getProject()).keySet()) {
for (PsiMethod method : map.get(superType)) {
if (!processor.execute(method, state)) {
return false;
}
}
}
return true;
}
});
}
public static MultiMap<String, PsiMethod> retrieveMethodMap(final Project project,
final GlobalSearchScope scope,
final Function<PsiMethod, PsiMethod> converter,
@NotNull final PsiClass categoryClass) {
return CachedValuesManager.getManager(project)
.getCachedValue(categoryClass, METHOD_KEY, new CachedValueProvider<MultiMap<String, PsiMethod>>() {
@Override
public Result<MultiMap<String, PsiMethod>> compute() {
MultiMap<String, PsiMethod> map = new MultiMap<String, PsiMethod>();
PsiManager manager = PsiManager.getInstance(project);
for (PsiMethod m : categoryClass.getMethods()) {
final PsiParameter[] params = m.getParameterList().getParameters();
if (params.length == 0) continue;
final PsiType parameterType = TypesUtil.boxPrimitiveType(params[0].getType(), manager, scope);
PsiType targetType = TypeConversionUtil.erasure(parameterType);
map.putValue(targetType.getCanonicalText(), converter.fun(m));
}
return Result.create(map, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, ProjectRootManager.getInstance(project));
}
}, false);
}
}
@@ -80,38 +80,42 @@ public class GroovyInlineMethodUtil {
return null;
}
PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null;
if (!invokedOnReference || reference == null) {
String message = GroovyRefactoringBundle.message("multiple.method.inline.is.not.suppored", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return null;
}
if (invokedOnReference) {
PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null;
if (reference == null) return null;
PsiElement element = reference.getElement();
PsiElement element = reference.getElement();
if (element.getContainingFile() instanceof GroovyFile) {
if (!(isStaticMethod(method) || areInSameClass(element, method))) { // todo implement for other cases
if (element.getContainingFile() instanceof GroovyFile) {
if (!(isStaticMethod(method) || areInSameClass(element, method))) { // todo implement for other cases
// showErrorMessage("Other class support will be implemented soon", myProject);
// return null;
}
}
if (!(element instanceof GrExpression && element.getParent() instanceof GrCallExpression)) {
String message = GroovyRefactoringBundle.message("refactoring.is.available.only.for.method.calls", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return null;
}
GrCallExpression call = (GrCallExpression)element.getParent();
if (PsiTreeUtil.getParentOfType(element, GrParameter.class) != null) {
String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.in.parameter.initializers", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return null;
}
GroovyRefactoringUtil.highlightOccurrences(project, editor, new GrExpression[]{call});
if (hasBadReturns(method) && !isTailMethodCall(call)) {
String message = GroovyRefactoringBundle
.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return null;
}
}
if (!(element instanceof GrExpression && element.getParent() instanceof GrCallExpression)) {
String message = GroovyRefactoringBundle.message("refactoring.is.available.only.for.method.calls", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return null;
}
GrCallExpression call = (GrCallExpression) element.getParent();
if (PsiTreeUtil.getParentOfType(element, GrParameter.class) != null) {
String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.in.parameter.initializers", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return null;
}
GroovyRefactoringUtil.highlightOccurrences(project, editor, new GrExpression[]{call});
if (method.getBlock() == null) {
String message;
if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
@@ -123,12 +127,6 @@ public class GroovyInlineMethodUtil {
return null;
}
if (hasBadReturns(method) && !isTailMethodCall(call)) {
String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return null;
}
return inlineMethodDialogResult(method, project, invokedOnReference);
}
@@ -48,11 +48,15 @@ class GroovyTransformationsTest extends LightCodeInsightFixtureTestCase {
public void testVetoableTransform() throws Throwable { doPlainTest() }
public void testNewifyTransform1() throws Throwable { doVariantsTest('newInstance', 'new', 'new', 'new',
public void testNewifyTransform1() throws Throwable { doVariantsTest('newInstance', 'new', 'new',
'newInstance', 'newInstance0', 'newInstanceCallerCache', 'next') }
public void testNewifyTransform2() throws Throwable { doVariantsTest('Leaf', 'Leaf', 'Leaf') }
public void testNewifyTransform3() throws Throwable { doVariantsTest('Bazz', 'Bazz') }
@Newify rubyLikeNew() {
assert Integer.ne == 42
}
}