Merge remote-tracking branch 'origin/master'

This commit is contained in:
Sascha Weinreuter
2013-01-16 16:58:16 +01:00
32 changed files with 464 additions and 543 deletions
@@ -521,11 +521,10 @@ public class CompileDriver {
@Override
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
compileContext.addMessage(CompilerMessageCategory.ERROR, failure.getDescription(), null, -1, -1);
final String trace = failure.getStacktrace();
compileContext.addMessage(CompilerMessageCategory.ERROR, failure.hasDescription()? failure.getDescription() : "", null, -1, -1);
final String trace = failure.hasStacktrace()? failure.getStacktrace() : null;
if (trace != null) {
LOG.info(trace);
System.out.println(trace);
}
compileContext.putUserData(COMPILE_SERVER_BUILD_STATUS, ExitStatus.ERRORS);
}
@@ -110,7 +110,11 @@ class AutoMakeMessageHandler extends DefaultMessageHandler {
@Override
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
final String msg = "Auto make failure: " + failure.getDescription();
String descr = failure.hasDescription() ? failure.getDescription() : null;
if (descr == null) {
descr = failure.hasStacktrace()? failure.getStacktrace() : "";
}
final String msg = "Auto make failure: " + descr;
CompilerManager.NOTIFICATION_GROUP.createNotification(msg, MessageType.INFO);
ProblemsView.SERVICE.getInstance(myProject).addMessage(new CompilerMessageImpl(myProject, CompilerMessageCategory.ERROR, msg), sessionId);
}
@@ -554,7 +554,7 @@ public class BuildManager implements ApplicationComponent{
projectTaskQueue.submit(new Runnable() {
@Override
public void run() {
ExecutionException execFailure = null;
Throwable execFailure = null;
try {
if (project.isDisposed()) {
return;
@@ -595,7 +595,7 @@ public class BuildManager implements ApplicationComponent{
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
}
}
catch (ExecutionException e) {
catch (Throwable e) {
execFailure = e;
}
finally {
@@ -690,12 +690,18 @@ public class BuildManager implements ApplicationComponent{
int sdkMinorVersion = 0;
final Set<Sdk> candidates = new HashSet<Sdk>();
final Sdk defaultSdk = ProjectRootManager.getInstance(project).getProjectSdk();
if (defaultSdk != null && defaultSdk.getSdkType() instanceof JavaSdk) {
candidates.add(defaultSdk);
}
for (Module module : ModuleManager.getInstance(project).getModules()) {
final Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
if (sdk != null && sdk.getSdkType() instanceof JavaSdk) {
candidates.add(sdk);
}
}
// now select the latest version from the sdks that are used in the project, but not older than the internal sdk version
for (Sdk candidate : candidates) {
final String vs = candidate.getVersionString();
@@ -269,7 +269,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
for (int i = 0; i < lambdaParameters.length; i++) {
PsiParameter lambdaParameter = lambdaParameters[i];
if (!TypeConversionUtil.isAssignable(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult).substitute(parameters[i].getType()), lambdaParameter.getType())) {
if (!TypeConversionUtil.isAssignable(lambdaParameter.getType(),
GenericsUtil.eliminateWildcards(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult).substitute(parameters[i].getType())))) {
myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, lambdaParameter, incompatibleTypesMessage));
break;
}
@@ -79,6 +79,7 @@ public abstract class BaseMoveInitializerToMethodAction extends PsiElementBaseIn
final Collection<PsiMethod> methodsToAddInitialization = getOrCreateMethods(project, editor, element.getContainingFile(), aClass);
if (methodsToAddInitialization.isEmpty()) return;
final List<PsiExpressionStatement> assignments = addFieldAssignments(field, methodsToAddInitialization);
field.getInitializer().delete();
@@ -108,8 +108,9 @@ public abstract class JavaTestFramework implements TestFramework {
return null;
}
protected PsiMethod createSetUpPatternMethod(JVMElementFactory factory) {
public PsiMethod createSetUpPatternMethod(JVMElementFactory factory) {
final FileTemplate template = FileTemplateManager.getInstance().getCodeTemplate(getSetUpMethodFileTemplateDescriptor().getFileName());
return factory.createMethodFromText(StringUtil.replace(template.getText(), "${BODY}\n", ""), null);
final String templateText = StringUtil.replace(StringUtil.replace(template.getText(), "${BODY}\n", ""), "${NAME}", "setUp");
return factory.createMethodFromText(templateText, null);
}
}
@@ -18,9 +18,14 @@ package com.intellij.testIntegration.intention;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.TestFrameworks;
import com.intellij.codeInsight.intention.impl.BaseMoveInitializerToMethodAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testIntegration.JavaTestFramework;
import com.intellij.testIntegration.TestFramework;
import com.intellij.testIntegration.TestIntegrationUtils;
import org.jetbrains.annotations.NotNull;
@@ -32,6 +37,8 @@ import java.util.Collections;
* @author cdr
*/
public class MoveInitializerToSetUpMethodAction extends BaseMoveInitializerToMethodAction {
private static final Logger LOG = Logger.getInstance("#" + MoveInitializerToSetUpMethodAction.class.getName());
@Override
@NotNull
public String getFamilyName() {
@@ -46,7 +53,27 @@ public class MoveInitializerToSetUpMethodAction extends BaseMoveInitializerToMet
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
return super.isAvailable(project, editor, element) && TestIntegrationUtils.isTest(element);
final boolean isAvailable = super.isAvailable(project, editor, element) && TestIntegrationUtils.isTest(element);
if (isAvailable) {
final PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class);
LOG.assertTrue(field != null);
final PsiClass aClass = field.getContainingClass();
LOG.assertTrue(aClass != null);
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
for (TestFramework framework : Extensions.getExtensions(TestFramework.EXTENSION_NAME)) {
if (framework instanceof JavaTestFramework && framework.isTestClass(aClass)) {
try {
((JavaTestFramework)framework).createSetUpPatternMethod(elementFactory);
return true;
}
catch (Exception e) {
return false;
}
}
}
return true;
}
return false;
}
@NotNull
@@ -0,0 +1,9 @@
class Test {
public interface I<K, V> {
public V put(K k);
}
{
final I<? super Long, CharSequence> i = (Number n) -> n.toString();
}
}
@@ -1,7 +1,7 @@
class Test {
{
<error descr="Incompatible types. Found: '<lambda expression>', required: 'java.lang.Comparable'">Comparable c = (String o)->{
Comparable c = (<error descr="Incompatible parameter types in lambda expression">String o</error>)->{
return 0;
};</error>
};
}
}
@@ -60,14 +60,14 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
}
""")
type('i')
assertContains("if", "iterable", "int")
assertContains("iterable", "if", "int")
type('t')
assertContains "iterable"
assertEquals 'iterable', lookup.currentItem.lookupString
type('er')
assertContains("iter", "iterable")
assertContains "iterable", "iter"
assertEquals 'iterable', lookup.currentItem.lookupString
assert lookup.focused
@@ -76,7 +76,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
}
def assertContains(String... items) {
assert myFixture.lookupElementStrings.containsAll(items as List)
myFixture.assertPreferredCompletionItems(0, items)
}
public void testRecalculateItemsOnBackspace() {
@@ -89,7 +89,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
}
""")
type "r"
assertContains "iter", "iterable"
assertContains "iterable", "iter"
type '\b'
assertContains "iterable"
@@ -104,7 +104,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
assertContains "iterable"
type "r"
assertContains "iter", "iterable"
assertContains "iterable", "iter"
}
public void testExplicitSelectionShouldSurvive() {
@@ -124,8 +124,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
assertEquals 'iterable2', lookup.currentItem.lookupString
type "r"
assertContains "iter", "iterable", 'iterable2'
assertEquals 'iterable2', lookup.currentItem.lookupString
myFixture.assertPreferredCompletionItems 2, "iterable", "iter", 'iterable2'
}
@@ -146,8 +145,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
assertEquals 'iterable2', lookup.currentItem.lookupString
type "r"
assertContains "iter", "iterable", 'iterable2'
assertEquals 'iterable2', lookup.currentItem.lookupString
myFixture.assertPreferredCompletionItems 2, "iterable", "iter", 'iterable2'
}
@@ -554,7 +552,7 @@ public interface Test {
""")
type('i')
def offset = myFixture.editor.caretModel.offset
assertContains "if", "iterable", "int"
assertContains "iterable", "if", "int"
edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT) }
assert myFixture.editor.caretModel.offset == offset + 1
@@ -569,7 +567,7 @@ public interface Test {
joinAutopopup()
joinCompletion()
assert !lookup.calculating
assertContains "if", "iterable", "int"
assertContains "iterable", "if", "int"
assertEquals 'iterable', lookup.currentItem.lookupString
edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT) }
@@ -656,26 +654,6 @@ public interface Test {
}
}
public void testTemplateSelectionByComma() {
myFixture.configureByText("a.java", """
class Foo {
int itea = 2;
int itera = 2;
{
it<caret>
}
}
""")
type 'e'
assertContains "itea", "itera"
type 'r'
assertContains "iter", "itera"
type ','
assert !lookup
assert myFixture.editor.document.text.contains('itera,')
}
public void testTemplateSelectionBySpace() {
myFixture.configureByText("a.java", """
class Foo {
@@ -959,7 +937,7 @@ class Foo {
}
type('_')
assertContains 'x__foo', 'x__goo'
myFixture.assertPreferredCompletionItems 1, 'x__foo', 'x__goo'
edt {
assert goo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP)
@@ -1076,14 +1054,6 @@ public class UTest {
return editor
}
public void _testCharSelectionUndo() {
myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
def editor = openEditorForUndo();
type('ArrStoExce.')
edt { UndoManager.getInstance(project).undo(editor) }
assert myFixture.editor.document.text.contains('ArrStoExce.')
}
public void testAutopopupTypingUndo() {
myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
def editor = openEditorForUndo();
@@ -41,6 +41,10 @@ public class LambdaParamsTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testFormalParamsWithWildcards() throws Exception {
doTest();
}
private void doTest() throws Exception {
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
}
@@ -127,7 +127,9 @@ public class CmdlineProtoUtil {
public static CmdlineRemoteProto.Message.Failure createFailure(String description, @Nullable Throwable cause) {
final CmdlineRemoteProto.Message.Failure.Builder builder = CmdlineRemoteProto.Message.Failure.newBuilder();
builder.setDescription(description);
if (description != null) {
builder.setDescription(description);
}
if (cause != null) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream stream = new PrintStream(baos);
@@ -137,7 +139,11 @@ public class CmdlineProtoUtil {
finally {
stream.close();
}
builder.setStacktrace(new String(baos.toByteArray()));
final String stacktrace = new String(baos.toByteArray());
builder.setStacktrace(stacktrace);
if (description == null) {
builder.setDescription(stacktrace);
}
}
return builder.build();
}
@@ -230,7 +230,15 @@ public class CompletionLookupArranger extends LookupArranger {
ensureItemAdded(items, model, byRelevance, relevantSelection);
ensureEverythingVisibleAdded(lookup, model, byRelevance);
return new ArrayList<LookupElement>(model);
ArrayList<LookupElement> result = new ArrayList<LookupElement>(model);
if (result.size() > 1) {
LookupElement first = result.get(0);
if (isLiveTemplate(first) && isPrefixItem(lookup, first, true)) {
ContainerUtil.swapElements(result, 0, 1);
}
}
return result;
}
private static void ensureEverythingVisibleAdded(LookupImpl lookup, final LinkedHashSet<LookupElement> model, Iterator<LookupElement> byRelevance) {
@@ -17,19 +17,22 @@
package com.intellij.codeInsight.lookup.impl;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.completion.CodeCompletionFeatures;
import com.intellij.codeInsight.completion.CompletionLookupArranger;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.completion.ShowHideIntentionIconLookupAction;
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.lookup.*;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.ui.UISettings;
import com.intellij.lang.LangBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
@@ -63,6 +66,7 @@ import com.intellij.ui.popup.AbstractPopup;
import com.intellij.util.Alarm;
import com.intellij.util.CollectConsumer;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.AbstractLayoutManager;
@@ -216,15 +220,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
mySortingLabel.setBorder(new LineBorder(Color.LIGHT_GRAY));
mySortingLabel.setOpaque(true);
new ClickListener() {
@Override
public boolean onClick(MouseEvent e, int clickCount) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_CHANGE_SORTING);
UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY = !UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY;
updateSorting();
return true;
}
}.installOn(mySortingLabel);
new ChangeLookupSorting().installOn(mySortingLabel);
updateSorting();
myModalityState = ModalityState.stateForComponent(getComponent());
}
@@ -254,7 +250,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
});
}
private void updateSorting() {
void updateSorting() {
final boolean lexi = UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY;
mySortingLabel.setIcon(lexi ? AllIcons.Ide.LookupAlphanumeric : AllIcons.Ide.LookupRelevance);
mySortingLabel.setToolTipText(lexi ? "Click to sort variants by relevance" : "Click to sort variants alphabetically");
@@ -1488,4 +1484,31 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
void setPreview(CompletionPreview preview) {
myPreview = preview;
}
private class ChangeLookupSorting extends ClickListener {
@Override
public boolean onClick(MouseEvent e, int clickCount) {
DataContext context = DataManager.getInstance().getDataContext(mySortingLabel);
DefaultActionGroup group = new DefaultActionGroup();
group.add(createSortingAction(true));
group.add(createSortingAction(false));
JBPopupFactory.getInstance().createActionGroupPopup("Change sorting", group, context, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false).showInBestPositionFor(
context);
return true;
}
private AnAction createSortingAction(boolean checked) {
boolean currentSetting = UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY;
final boolean newSetting = checked ? currentSetting : !currentSetting;
return new AnAction(newSetting ? "Sort lexicographically" : "Sort by relevance", null, checked ? PlatformIcons.CHECK_ICON : null) {
@Override
public void actionPerformed(AnActionEvent e) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_CHANGE_SORTING);
UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY = newSetting;
updateSorting();
}
};
}
}
}
@@ -28,11 +28,7 @@ import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.impl.TemplateSettings;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.util.TextRange;
@@ -54,11 +50,6 @@ public abstract class ChooseItemAction extends EditorAction {
this.finishingChar = finishingChar;
}
@Override
public boolean executeInCommand(Editor editor, DataContext dataContext) {
return false;
}
@Override
public void execute(@NotNull final Editor editor, final DataContext dataContext) {
final LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
@@ -77,18 +68,8 @@ public abstract class ChooseItemAction extends EditorAction {
} else if (finishingChar == '.') {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_FINISH_BY_CONTROL_DOT);
}
lookup.uninstallPreview();
Runnable command = new Runnable() {
@Override
public void run() {
lookup.finishLookup(finishingChar);
}
};
Document doc = editor.getDocument();
DocCommandGroupId group = DocCommandGroupId.noneGroupId(doc);
CommandProcessor.getInstance().executeCommand(editor.getProject(), command, "Completion", group, UndoConfirmationPolicy.DEFAULT, doc);
lookup.finishLookup(finishingChar);
}
@@ -17,10 +17,18 @@
package com.intellij.refactoring.actions;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupEx;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.ide.IdeEventQueue;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
@@ -87,7 +95,22 @@ public abstract class BaseRefactoringAction extends AnAction {
InplaceRefactoring.unableToStartWarning(project, editor);
return;
}
final LookupEx lookup = LookupManager.getActiveLookup(editor);
if (lookup instanceof LookupImpl) {
Runnable command = new Runnable() {
@Override
public void run() {
((LookupImpl)lookup).finishLookup(Lookup.NORMAL_SELECT_CHAR);
}
};
assert editor != null;
Document doc = editor.getDocument();
DocCommandGroupId group = DocCommandGroupId.noneGroupId(doc);
CommandProcessor.getInstance().executeCommand(editor.getProject(), command, "Completion", group, UndoConfirmationPolicy.DEFAULT, doc);
}
IdeEventQueue.getInstance().setEventCount(eventCount);
if (editor != null) {
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
@@ -32,7 +32,6 @@ import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.options.TabbedConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -96,9 +95,8 @@ public class GenerateToStringActionHandlerImpl extends EditorWriteActionHandler
final MemberChooserBuilder<PsiElementClassMember> builder = new MemberChooserBuilder<PsiElementClassMember>(project);
final MemberChooserHeaderPanel header = new MemberChooserHeaderPanel(clazz);
builder.setHeaderPanel(header);
boolean isJdk15Enabled = PsiUtil.isLanguageLevel5OrHigher(clazz);
builder.overrideAnnotationVisible(isJdk15Enabled);
builder.setTitle(calcCurrentTitle());
builder.overrideAnnotationVisible(PsiUtil.isLanguageLevel5OrHigher(clazz));
builder.setTitle("Generate toString()");
logger.debug("Displaying member chooser dialog");
SwingUtilities.invokeLater(new Runnable() {
@@ -120,7 +118,7 @@ public class GenerateToStringActionHandlerImpl extends EditorWriteActionHandler
GenerateToStringWorker.executeGenerateActionLater(clazz, editor, selectedMembers, template, dialog.isInsertOverrideAnnotation());
}
else {
Messages.showWarningDialog("The template chosen is invalid.", "Broken Template");
HintManager.getInstance().showErrorHint(editor, "toString() template '" + template.getFileName() + "' is invalid");
}
}
}
@@ -129,39 +127,23 @@ public class GenerateToStringActionHandlerImpl extends EditorWriteActionHandler
logger.debug("+++ doExecuteAction - END +++");
}
private static String calcCurrentTitle() {
final TemplateResource template = TemplatesManager.getInstance().getDefaultTemplate();
if (template.isValidTemplate()) {
return "Generate " + template.getTargetMethodName();
}
else {
return "Generate";
}
}
public static void updateDialog(PsiClass clazz, MemberChooser<PsiElementClassMember> dialog) {
dialog.setTitle(calcCurrentTitle());
final PsiElementClassMember[] members = buildMembersToShow(clazz);
dialog.resetElements(members);
dialog.selectElements(members);
}
private static PsiElementClassMember[] buildMembersToShow(PsiClass clazz) {
Project project = clazz.getProject();
PsiAdapter psi = PsiAdapterFactory.getPsiAdapter();
Config config = GenerateToStringContext.getConfig();
PsiField[] filteredFields = GenerateToStringUtils.filterAvailableFields(project, psi, clazz, config.getFilterPattern());
PsiField[] filteredFields = GenerateToStringUtils.filterAvailableFields(clazz, config.getFilterPattern());
if (logger.isDebugEnabled()) logger.debug("Number of fields after filtering: " + filteredFields.length);
if (logger.isDebugEnabled()) logger.debug("Number of fields after filtering: " + filteredFields.length);
PsiMethod[] filteredMethods = new PsiMethod[0];
PsiMethod[] filteredMethods;
if (config.enableMethods) {
// filter methods as it is enabled from config
filteredMethods = GenerateToStringUtils.filterAvailableMethods(psi, clazz, config.getFilterPattern());
filteredMethods = GenerateToStringUtils.filterAvailableMethods(clazz, config.getFilterPattern());
if (logger.isDebugEnabled()) logger.debug("Number of methods after filtering: " + filteredMethods.length);
} else {
filteredMethods = PsiMethod.EMPTY_ARRAY;
}
return GenerateToStringUtils.combineToClassMemberList(filteredFields, filteredMethods);
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007 the original author or authors.
* Copyright 2001-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.generate.tostring.config.FilterPattern;
import org.jetbrains.generate.tostring.element.ElementFactory;
import org.jetbrains.generate.tostring.element.FieldElement;
@@ -48,23 +49,22 @@ public class GenerateToStringUtils {
/**
* Filters the list of fields from the class with the given parameters from the {@link org.jetbrains.generate.tostring.config.Config config} settings.
*
* @param project Project
* @param psi PSI adapter
* @param clazz the class to filter it's fields
* @param pattern the filter pattern to filter out unwanted fields
* @return fields avaiable for this action after the filter process.
* @return fields available for this action after the filter process.
*/
public static PsiField[] filterAvailableFields(Project project, PsiAdapter psi, PsiClass clazz, FilterPattern pattern) {
@NotNull
public static PsiField[] filterAvailableFields(PsiClass clazz, FilterPattern pattern) {
if (log.isDebugEnabled()) log.debug("Filtering fields using the pattern: " + pattern);
List<PsiField> availableFields = new ArrayList<PsiField>();
// performs til filtering process
PsiField[] fields = clazz.getFields();
PsiField[] fields = clazz.getFields();
for (PsiField field : fields) {
FieldElement fe = ElementFactory.newFieldElement(project, field, psi);
FieldElement fe = ElementFactory.newFieldElement(field);
if (log.isDebugEnabled()) log.debug("Field being filtered: " + fe);
// if the field matches the pattern then it shouldn't be in the list of avaialble fields
// if the field matches the pattern then it shouldn't be in the list of available fields
if (!fe.applyFilter(pattern)) {
availableFields.add(field);
}
@@ -81,51 +81,53 @@ public class GenerateToStringUtils {
* <li/>public, non static, non abstract
* <ul/>
*
* @param psi PSI adapter
*
* @param clazz the class to filter it's fields
* @param pattern the filter pattern to filter out unwanted fields
* @return methods avaiable for this action after the filter process.
* @return methods available for this action after the filter process.
*/
public static PsiMethod[] filterAvailableMethods(PsiAdapter psi, PsiClass clazz, FilterPattern pattern) {
@NotNull
public static PsiMethod[] filterAvailableMethods(PsiClass clazz, @NotNull FilterPattern pattern) {
if (log.isDebugEnabled()) log.debug("Filtering methods using the pattern: " + pattern);
List<PsiMethod> availableMethods = new ArrayList<PsiMethod>();
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(clazz.getProject()).getElementFactory();
PsiMethod[] methods = clazz.getMethods();
PsiMethod[] methods = clazz.getMethods();
for (PsiMethod method : methods) {
MethodElement me = ElementFactory.newMethodElement(method, elementFactory, psi);
if (log.isDebugEnabled()) log.debug("Method being filtered: " + me);
// the method should be a getter
if (!me.isGetter()) {
if (!PsiAdapter.isGetterMethod(method)) {
continue;
}
// must not return void
if (me.isReturnTypeVoid()) {
final PsiType returnType = method.getReturnType();
if (returnType == null || PsiType.VOID.equals(returnType)) {
continue;
}
// method should be public, non static, non abstract
if (!me.isModifierPublic() || me.isModifierStatic() || me.isModifierAbstract()) {
if (!method.hasModifierProperty(PsiModifier.PUBLIC) || method.hasModifierProperty(PsiModifier.STATIC) ||
method.hasModifierProperty(PsiModifier.ABSTRACT)) {
continue;
}
// method should not be a getter for an existing field
if (clazz.findFieldByName(me.getFieldName(), false) != null) {
String fieldName = PsiAdapter.getGetterFieldName(method);
if (clazz.findFieldByName(fieldName, false) != null) {
continue;
}
// must not be named toString or getClass
if ("toString".equals(me.getMethodName()) || "getClass".equals(me.getMethodName())) {
final String methodName = method.getName();
if ("toString".equals(methodName) || "getClass".equals(methodName)) {
continue;
}
// if the method matches the pattern then it shouldn't be in the list of avaialble methods
// if the method matches the pattern then it shouldn't be in the list of available methods
MethodElement me = ElementFactory.newMethodElement(method);
if (!me.applyFilter(pattern)) {
if (log.isDebugEnabled())
log.debug("Adding the method " + method.getName() + " as there is not a field for this getter");
log.debug("Adding the method " + methodName + " as there is not a field for this getter");
availableMethods.add(method);
}
}
@@ -133,7 +135,7 @@ public class GenerateToStringUtils {
return availableMethods.toArray(new PsiMethod[availableMethods.size()]);
}
/**
/**
* Handles any exception during the executing on this plugin.
*
* @param project PSI project
@@ -144,7 +146,7 @@ public class GenerateToStringUtils {
log.info(e);
if (e instanceof GenerateCodeException) {
// code generation error - display velocity errror in error dialog so user can identify problem quicker
// code generation error - display velocity error in error dialog so user can identify problem quicker
Messages.showMessageDialog(project, "Velocity error generating code - see IDEA log for more details (stacktrace should be in idea.log):\n" + e.getMessage(), "Warning", Messages.getWarningIcon());
} else if (e instanceof PluginException) {
// plugin related error - could be recoverable.
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@
*/
package org.jetbrains.generate.tostring;
import com.intellij.codeInsight.intention.AddAnnotationFix;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -29,17 +28,16 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.util.IncorrectOperationException;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.generate.tostring.config.*;
import org.jetbrains.generate.tostring.element.*;
import org.jetbrains.generate.tostring.exception.GenerateCodeException;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import org.jetbrains.generate.tostring.psi.PsiAdapterFactory;
import org.jetbrains.generate.tostring.template.TemplateResource;
import org.jetbrains.generate.tostring.velocity.VelocityFactory;
import org.jetbrains.generate.tostring.view.MethodExistsDialog;
@@ -50,13 +48,10 @@ import java.util.*;
public class GenerateToStringWorker {
private static final Logger logger = Logger.getInstance("#org.jetbrains.generate.tostring.GenerateToStringWorker");
private final PsiElementFactory elementFactory;
private final JVMElementFactory topLevelFactory;
private final CodeStyleManager codeStyleManager;
private final Editor editor;
private final PsiFile containingFile;
private final PsiClass clazz;
private final PsiAdapter psi;
private final Config config;
private final Project project;
private final boolean hasOverrideAnnotation;
@@ -64,12 +59,9 @@ public class GenerateToStringWorker {
public GenerateToStringWorker(PsiClass clazz, Editor editor, boolean insertAtOverride) {
this.clazz = clazz;
this.project = clazz.getProject();
this.psi = PsiAdapterFactory.getPsiAdapter();
this.editor = editor;
this.elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
this.topLevelFactory = JVMElementFactories.getFactory(clazz.getLanguage(), project);
this.codeStyleManager = CodeStyleManager.getInstance(project);
this.containingFile = clazz.getContainingFile();
this.config = GenerateToStringContext.getConfig();
this.hasOverrideAnnotation = insertAtOverride;
}
@@ -109,7 +101,7 @@ public class GenerateToStringWorker {
}
/**
* This method get's the choice if there is an existing <code>toString</code> method.
* This method gets the choice if there is an existing <code>toString</code> method.
* <br/> 1) If there is a settings to always override use this.
* <br/> 2) Prompt a dialog and let the user decide.
*
@@ -119,7 +111,7 @@ public class GenerateToStringWorker {
private ConflictResolutionPolicy exitsMethodDialog(TemplateResource template) {
final DuplicatonPolicy dupPolicy = config.getReplaceDialogInitialOption();
if (dupPolicy == DuplicatonPolicy.ASK) {
PsiMethod existingMethod = psi.findMethodByName(clazz, template.getTargetMethodName());
PsiMethod existingMethod = PsiAdapter.findMethodByName(clazz, template.getTargetMethodName());
if (existingMethod != null) {
return MethodExistsDialog.showDialog(template.getTargetMethodName());
}
@@ -139,7 +131,7 @@ public class GenerateToStringWorker {
* @param template the template to use
*/
private void beforeCreateToStringMethod(Map<String, String> params, TemplateResource template) {
PsiMethod existingMethod = psi.findMethodByName(clazz, template.getTargetMethodName()); // find the existing method
PsiMethod existingMethod = PsiAdapter.findMethodByName(clazz, template.getTargetMethodName()); // find the existing method
if (existingMethod != null && existingMethod.getDocComment() != null) {
PsiDocComment doc = existingMethod.getDocComment();
if (doc != null) {
@@ -172,7 +164,7 @@ public class GenerateToStringWorker {
body = StringUtil.convertLineSeparators(body);
// create psi newMethod named toString()
PsiMethod newMethod = topLevelFactory.createMethodFromText(template.getMethodSignature() + " { " + body + " }", null);
PsiMethod newMethod = topLevelFactory.createMethodFromText(template.getMethodSignature() + " { " + body + " }", clazz);
codeStyleManager.reformat(newMethod);
// insertNewMethod conflict resolution policy (add/replace, duplicate, cancel)
@@ -183,17 +175,7 @@ public class GenerateToStringWorker {
}
if (hasOverrideAnnotation) {
annotate(toStringMethod, "java.lang.Override");
}
// add annotations
if (template.hasAnnotations()) {
String[] annotations = template.getAnnotations();
// must reverse loop to add annotations in the same order as in the template (when inserting it would insert in top)
for (int i = annotations.length - 1; i > -1; i--) {
String text = annotations[i];
psi.addAnnotationToMethod(topLevelFactory, toStringMethod, text);
}
toStringMethod.getModifierList().addAnnotation("java.lang.Override");
}
// applyJavaDoc conflict resolution policy (add or keep existing)
@@ -204,20 +186,16 @@ public class GenerateToStringWorker {
newJavaDoc = velocityGenerateCode(selectedMembers, params, newJavaDoc);
if (logger.isDebugEnabled()) logger.debug("JavaDoc body generated from Velocity:\n" + newJavaDoc);
applyJavaDoc(toStringMethod, elementFactory, codeStyleManager, existingJavaDoc, newJavaDoc);
applyJavaDoc(toStringMethod, existingJavaDoc, newJavaDoc);
}
// return the created method
return toStringMethod;
}
private void applyJavaDoc(PsiMethod newMethod,
PsiElementFactory elementFactory,
CodeStyleManager codeStyleManager,
String existingJavaDoc,
String newJavaDoc) throws IncorrectOperationException {
private static void applyJavaDoc(PsiMethod newMethod, String existingJavaDoc, String newJavaDoc) {
String text = newJavaDoc != null ? newJavaDoc : existingJavaDoc; // prefer to use new javadoc
psi.addOrReplaceJavadoc(elementFactory, codeStyleManager, newMethod, text, true);
PsiAdapter.addOrReplaceJavadoc(newMethod, text, true);
}
@@ -229,24 +207,23 @@ public class GenerateToStringWorker {
* @param template the template to use
* @throws IncorrectOperationException is thrown by IDEA
*/
private void afterCreateToStringMethod(PsiMethod method, Map<String, String> params, TemplateResource template)
throws IncorrectOperationException {
private void afterCreateToStringMethod(PsiMethod method, Map<String, String> params, TemplateResource template) {
PsiFile containingFile = clazz.getContainingFile();
if (containingFile instanceof PsiJavaFile) {
final PsiJavaFile javaFile = (PsiJavaFile)containingFile;
// if the code uses Arrays, then make sure java.util.Arrays is imported.
String javaCode = method.getText();
if (javaCode.indexOf("Arrays.") > 0 &&
!(psi.hasImportStatement(javaFile, "java.util.*") || psi.hasImportStatement(javaFile, "java.util.Arrays"))) {
!(PsiAdapter.hasImportStatement(javaFile, "java.util.*") || PsiAdapter.hasImportStatement(javaFile, "java.util.Arrays"))) {
// java.util.Arrays must be imported as java.util.* since the addImportStatement method doens't support onDemand-import statement yet.
psi.addImportStatement(javaFile, "java.util.*", elementFactory);
PsiAdapter.addImportStatement(javaFile, "java.util.*");
}
// if the code uses Reflection (Field[]), then make sure java.lang.reflect.Field is imported.
if (javaCode.indexOf("Field[]") > 0 &&
!(psi.hasImportStatement(javaFile, "java.lang.reflect.*") || psi.hasImportStatement(javaFile, "java.lang.reflect.Field"))) {
!(PsiAdapter.hasImportStatement(javaFile, "java.lang.reflect.*") || PsiAdapter.hasImportStatement(javaFile, "java.lang.reflect.Field"))) {
// java.lang.reflect.Field must be imported as java.lang.reflect.* since the addImportStatement method doens't support onDemand-import statement yet.
psi.addImportStatement(javaFile, "java.lang.reflect.*", elementFactory);
PsiAdapter.addImportStatement(javaFile, "java.lang.reflect.*");
}
// any additional packages to import from the params
@@ -260,7 +237,7 @@ public class GenerateToStringWorker {
// jump to method
if (config.isJumpToMethod() && editor != null) {
PsiMethod newMethod = psi.findMethodByName(clazz, template.getTargetMethodName());
PsiMethod newMethod = PsiAdapter.findMethodByName(clazz, template.getTargetMethodName());
if (newMethod != null) {
int offset = newMethod.getTextOffset();
if (offset > 2) {
@@ -279,12 +256,12 @@ public class GenerateToStringWorker {
* @param packageNames names of packages (must end with .* and be seperated by ; or ,)
* @throws IncorrectOperationException error adding imported package
*/
private void autoImportPackages(PsiJavaFile psiJavaFile, String packageNames) throws IncorrectOperationException {
private static void autoImportPackages(PsiJavaFile psiJavaFile, String packageNames) throws IncorrectOperationException {
StringTokenizer tok = new StringTokenizer(packageNames, ",");
while (tok.hasMoreTokens()) {
String packageName = tok.nextToken().trim(); // trim in case of space
if (logger.isDebugEnabled()) logger.debug("Auto importing package: " + packageName);
psi.addImportStatement(psiJavaFile, packageName, elementFactory);
PsiAdapter.addImportStatement(psiJavaFile, packageName);
}
}
@@ -295,7 +272,7 @@ public class GenerateToStringWorker {
*
* @param selectedMembers the selected members as both {@link com.intellij.psi.PsiField} and {@link com.intellij.psi.PsiMethod}.
* @param params additional parameters stored with key/value in the map.
* @param templateMacro the veloicty macro template
* @param templateMacro the velocity macro template
* @return code (usually javacode). Returns null if templateMacro is null.
* @throws GenerateCodeException is thrown when there is an error generating the javacode.
*/
@@ -311,15 +288,15 @@ public class GenerateToStringWorker {
// field information
logger.debug("Velocity Context - adding fields");
vc.put("fields", ElementUtils.getOnlyAsFieldElements(project, psi, selectedMembers));
vc.put("fields", ElementUtils.getOnlyAsFieldElements(selectedMembers));
// method information
logger.debug("Velocity Context - adding methods");
vc.put("methods", ElementUtils.getOnlyAsMethodElements(elementFactory, psi, selectedMembers));
vc.put("methods", ElementUtils.getOnlyAsMethodElements(selectedMembers));
// element information (both fields and methods)
logger.debug("Velocity Context - adding members (fields and methods)");
List<Element> elements = ElementUtils.getOnlyAsFieldAndMethodElements(project, elementFactory, psi, selectedMembers);
List<Element> elements = ElementUtils.getOnlyAsFieldAndMethodElements(selectedMembers);
// sort elements if enabled and not using chooser dialog
if (config.getSortElements() != 0) {
Collections.sort(elements, new ElementComparator(config.getSortElements()));
@@ -327,11 +304,11 @@ public class GenerateToStringWorker {
vc.put("members", elements);
// class information
ClassElement ce = ElementFactory.newClassElement(project, clazz, psi);
ClassElement ce = ElementFactory.newClassElement(clazz);
vc.put("class", ce);
if (logger.isDebugEnabled()) logger.debug("Velocity Context - adding class: " + ce);
// information to keep as it is to avoid breaking compability with prior releases
// information to keep as it is to avoid breaking compatibility with prior releases
vc.put("classname", config.isUseFullyQualifiedName() ? ce.getQualifiedName() : ce.getName());
vc.put("FQClassname", ce.getQualifiedName());
@@ -348,9 +325,9 @@ public class GenerateToStringWorker {
params.put("autoImportPackages", (String)vc.get("autoImportPackages"));
}
// add java.io.Serializable if choosen in [settings] and does not already implements it
// add java.io.Serializable if chosen in [settings] and does not already implements it
if (config.isAddImplementSerializable() && !ce.isImplements("java.io.Serializable")) {
psi.addImplements(project, clazz, "java.io.Serializable");
PsiAdapter.addImplements(clazz, "java.io.Serializable");
}
}
@@ -365,13 +342,13 @@ public class GenerateToStringWorker {
* Generates the toString() code for the specified class and selected
* fields, doing the work through a WriteAction ran by a CommandProcessor.
*
* @param selectedMemebers list of members selected
* @param selectedMembers list of members selected
* @param template the choosen template to use
* @param insertAtOverride
*/
public static void executeGenerateActionLater(final PsiClass clazz,
final Editor editor,
final Collection<PsiMember> selectedMemebers,
final Collection<PsiMember> selectedMembers,
final TemplateResource template,
final boolean insertAtOverride) {
Runnable writeCommand = new Runnable() {
@@ -379,7 +356,7 @@ public class GenerateToStringWorker {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
try {
new GenerateToStringWorker(clazz, editor, insertAtOverride).execute(selectedMemebers, template);
new GenerateToStringWorker(clazz, editor, insertAtOverride).execute(selectedMembers, template);
}
catch (Exception e) {
GenerateToStringUtils.handleException(clazz.getProject(), e);
@@ -389,14 +366,6 @@ public class GenerateToStringWorker {
}
};
PsiAdapterFactory.getPsiAdapter().executeCommand(clazz.getProject(), writeCommand);
}
private static void annotate(@NotNull PsiMethod result, String fqn) throws IncorrectOperationException {
Project project = result.getProject();
AddAnnotationFix fix = new AddAnnotationFix(fqn, result);
if (fix.isAvailable(project, null, result.getContainingFile())) {
fix.invoke(project, null, result.getContainingFile());
}
PsiAdapter.executeCommand(clazz.getProject(), writeCommand);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007 the original author or authors.
* Copyright 2001-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,9 +19,8 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import org.jetbrains.generate.tostring.psi.PsiAdapterFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
/**
* Inserts the method after the hashCode/equals methods in the javafile.
@@ -29,26 +28,18 @@ import org.jetbrains.annotations.NotNull;
public class InsertAfterEqualsHashCodeStrategy implements InsertNewMethodStrategy {
private static final InsertAfterEqualsHashCodeStrategy instance = new InsertAfterEqualsHashCodeStrategy();
private static PsiAdapter psi;
private InsertAfterEqualsHashCodeStrategy() {
}
private InsertAfterEqualsHashCodeStrategy() {}
public static InsertAfterEqualsHashCodeStrategy getInstance() {
return instance;
}
public PsiMethod insertNewMethod(PsiClass clazz, @NotNull PsiMethod newMethod, Editor editor) throws IncorrectOperationException {
// lazy initialize otherwise IDEA throws error: Component requests are not allowed before they are created
if (psi == null) {
psi = PsiAdapterFactory.getPsiAdapter();
}
PsiMethod methodHashCode = PsiAdapter.findHashCodeMethod(clazz);
PsiMethod methodEquals = PsiAdapter.findEqualsMethod(clazz);
// if main method exists and is the last then add toString just before main method
PsiMethod methodHashCode = psi.findHashCodeMethod(clazz);
PsiMethod methodEquals = psi.findEqualsMethod(clazz);
// if both methos exist determine the last method in the javafile
// if both methods exist determine the last method in the javafile
PsiMethod method;
if (methodEquals != null && methodHashCode != null) {
if (methodEquals.getTextOffset() > methodHashCode.getTextOffset()) {
@@ -74,5 +65,4 @@ public class InsertAfterEqualsHashCodeStrategy implements InsertNewMethodStrateg
public String toString() {
return "After equals/hashCode";
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007 the original author or authors.
* Copyright 2001-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,9 +20,8 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import org.jetbrains.generate.tostring.psi.PsiAdapterFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
/**
* Inserts the method last in the javafile.
@@ -31,18 +30,16 @@ public class InsertLastStrategy implements InsertNewMethodStrategy {
private static final InsertLastStrategy instance = new InsertLastStrategy();
private InsertLastStrategy() {
}
private InsertLastStrategy() {}
public static InsertLastStrategy getInstance() {
return instance;
}
public PsiMethod insertNewMethod(PsiClass clazz, @NotNull PsiMethod newMethod, Editor editor) throws IncorrectOperationException {
PsiAdapter psi = PsiAdapterFactory.getPsiAdapter();
public PsiMethod insertNewMethod(PsiClass clazz, @NotNull PsiMethod newMethod, Editor editor) {
// if main method exists and is the last then add toString just before main method
PsiMethod mainMethod = psi.findPublicStaticVoidMainMethod(clazz);
PsiMethod mainMethod = PsiAdapter.findPublicStaticVoidMainMethod(clazz);
if (mainMethod != null) {
// add before main method if it is the last method
PsiMethod[] methods = clazz.getMethods();
@@ -30,7 +30,6 @@ public class ClassElement implements Serializable {
private String name;
private String qualifiedName;
private boolean hasSuper;
private String superName;
private String superQualifiedName;
private String[] implementNames;
@@ -123,12 +122,8 @@ public class ClassElement implements Serializable {
this.qualifiedName = FQClassname;
}
public boolean isHasSuper() {
return hasSuper;
}
public void setHasSuper(boolean hasSuper) {
this.hasSuper = hasSuper;
public boolean hasSuper() {
return this.superName != null;
}
public boolean isDeprecated() {
@@ -167,7 +162,6 @@ public class ClassElement implements Serializable {
return "ClassElement{" +
"name='" + name + "'" +
", qualifiedName='" + qualifiedName + "'" +
", hasSuper=" + hasSuper +
", superName='" + superName + "'" +
", superQualifiedName='" + superQualifiedName + "'" +
", implementNames=" + (implementNames == null ? null : Arrays.asList(implementNames)) +
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007 the original author or authors.
* Copyright 2001-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
package org.jetbrains.generate.tostring.element;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
@@ -33,12 +32,10 @@ public class ElementFactory {
/**
* Creates a new {@link ClassElement} object.
*
* @param project the IDEA project.
* @param clazz class information.
* @param psi the psi adapter
* @return a new {@link ClassElement} object.
*/
public static ClassElement newClassElement(Project project, PsiClass clazz, PsiAdapter psi) {
public static ClassElement newClassElement(PsiClass clazz) {
ClassElement ce = new ClassElement();
// name
@@ -46,12 +43,11 @@ public class ElementFactory {
ce.setQualifiedName(clazz.getQualifiedName());
// super
ce.setHasSuper(psi.hasSuperClass(project, clazz));
PsiClass superClass = psi.getSuperClass(project, clazz);
ce.setSuperName(superClass == null ? null : superClass.getName());
PsiClass superClass = clazz.getSuperClass();
ce.setSuperName((superClass == null) ? null : superClass.getName());
// interfaces
ce.setImplementNames(psi.getImplementsClassnames(clazz));
ce.setImplementNames(PsiAdapter.getImplementsClassnames(clazz));
// other
ce.setEnum(clazz.isEnum());
@@ -65,28 +61,24 @@ public class ElementFactory {
/**
* Create a new {@link FieldElement} object.
*
* @param project the IDEA project.
* @param field the {@link com.intellij.psi.PsiField} to get the information from.
* @param psi the psi adapter
* @return a new {@link FieldElement} object.
*/
public static FieldElement newFieldElement(Project project, PsiField field, PsiAdapter psi) {
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
public static FieldElement newFieldElement(PsiField field) {
FieldElement fe = new FieldElement();
PsiType type = field.getType();
fe.setName(field.getName());
if (psi.isConstantField(field)) fe.setConstant(true);
if (psi.isEnumField(field)) fe.setEnum(true);
if (PsiAdapter.isConstantField(field)) fe.setConstant(true);
if (PsiAdapter.isEnumField(field)) fe.setEnum(true);
PsiModifierList modifiers = field.getModifierList();
if (modifiers != null) {
if (modifiers.hasModifierProperty(PsiModifier.TRANSIENT)) fe.setModifierTransient(true);
if (modifiers.hasModifierProperty(PsiModifier.VOLATILE)) fe.setModifierVolatile(true);
}
setElementInfo(fe, factory, type, modifiers, psi);
PsiElementFactory factory = JavaPsiFacade.getInstance(field.getProject()).getElementFactory();
PsiType type = field.getType();
setElementInfo(fe, factory, type, modifiers);
return fe;
}
@@ -95,12 +87,10 @@ public class ElementFactory {
* Creates a new {@link MethodElement} object.
*
* @param method the PSI method object.
* @param factory the PsiAdapterFactory.
* @param psi the psi adapter
* @return a new {@link MethodElement} object.
* @since 2.15
*/
public static MethodElement newMethodElement(PsiMethod method, PsiElementFactory factory, PsiAdapter psi) {
public static MethodElement newMethodElement(PsiMethod method) {
MethodElement me = new MethodElement();
PsiType type = method.getReturnType();
PsiModifierList modifiers = method.getModifierList();
@@ -111,21 +101,21 @@ public class ElementFactory {
log.warn("This method does not have a valid return type: " + method.getName() + ", returnType=" + type);
return me;
}
setElementInfo(me, factory, type, modifiers, psi);
PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
setElementInfo(me, factory, type, modifiers);
// names
String fieldName = psi.getGetterFieldName(factory, method);
String fieldName = PsiAdapter.getGetterFieldName(method);
me.setName(fieldName == null ? method.getName() : fieldName);
me.setFieldName(fieldName);
me.setMethodName(method.getName());
// getter
me.setGetter(psi.isGetterMethod(factory, method));
me.setGetter(PsiAdapter.isGetterMethod(method));
// misc
me.setDeprecated(method.isDeprecated());
me.setReturnTypeVoid(psi.isTypeOfVoid(method.getReturnType()));
me.setReturnTypeVoid(PsiAdapter.isTypeOfVoid(method.getReturnType()));
// modifiers
if (modifiers.hasModifierProperty(PsiModifier.ABSTRACT)) me.setModifierAbstract(true);
@@ -138,48 +128,46 @@ public class ElementFactory {
* Sets the basic element information from the given type.
*
* @param element the element to set information from the type
* @param factory the PsiAdapterFactory.
* @param factory
* @param type the type
* @param psi the psi adapter.
* @param modifiers modifier list
* @since 2.15
*/
private static void setElementInfo(AbstractElement element,
PsiElementFactory factory,
PsiType type,
PsiModifierList modifiers,
PsiAdapter psi) {
PsiModifierList modifiers) {
// type names
element.setTypeName(psi.getTypeClassName(type));
element.setTypeQualifiedName(psi.getTypeQualifiedClassName(type));
element.setTypeName(PsiAdapter.getTypeClassName(type));
element.setTypeQualifiedName(PsiAdapter.getTypeQualifiedClassName(type));
// arrays, collections and maps types
if (psi.isObjectArrayType(type)) {
if (PsiAdapter.isObjectArrayType(type)) {
element.setObjectArray(true);
element.setArray(true);
// additional specify if the element is a string array
if (psi.isStringArrayType(type)) element.setStringArray(true);
if (PsiAdapter.isStringArrayType(type)) element.setStringArray(true);
}
else if (psi.isPrimitiveArrayType(type)) {
else if (PsiAdapter.isPrimitiveArrayType(type)) {
element.setPrimitiveArray(true);
element.setArray(true);
}
if (psi.isCollectionType(factory, type)) element.setCollection(true);
if (psi.isListType(factory, type)) element.setList(true);
if (psi.isSetType(factory, type)) element.setSet(true);
if (psi.isMapType(factory, type)) element.setMap(true);
if (PsiAdapter.isCollectionType(factory, type)) element.setCollection(true);
if (PsiAdapter.isListType(factory, type)) element.setList(true);
if (PsiAdapter.isSetType(factory, type)) element.setSet(true);
if (PsiAdapter.isMapType(factory, type)) element.setMap(true);
// other types
if (psi.isPrimitiveType(type)) element.setPrimitive(true);
if (psi.isObjectType(factory, type)) element.setObject(true);
if (psi.isStringType(factory, type)) element.setString(true);
if (psi.isNumericType(factory, type)) element.setNumeric(true);
if (psi.isDateType(factory, type)) element.setDate(true);
if (psi.isCalendarType(factory, type)) element.setCalendar(true);
if (psi.isBooleanType(factory, type)) element.setBoolean(true);
if (PsiAdapter.isPrimitiveType(type)) element.setPrimitive(true);
if (PsiAdapter.isObjectType(factory, type)) element.setObject(true);
if (PsiAdapter.isStringType(factory, type)) element.setString(true);
if (PsiAdapter.isNumericType(factory, type)) element.setNumeric(true);
if (PsiAdapter.isDateType(factory, type)) element.setDate(true);
if (PsiAdapter.isCalendarType(factory, type)) element.setCalendar(true);
if (PsiAdapter.isBooleanType(factory, type)) element.setBoolean(true);
// modifiers
if (modifiers != null) {
@@ -196,7 +184,5 @@ public class ElementFactory {
}
else if (modifiers.hasModifierProperty(PsiModifier.PRIVATE)) element.setModifierPrivate(true);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007 the original author or authors.
* Copyright 2001-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,9 @@
*/
package org.jetbrains.generate.tostring.element;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiMethod;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import java.util.ArrayList;
import java.util.Collection;
@@ -31,24 +28,21 @@ import java.util.List;
*/
public class ElementUtils {
private ElementUtils() {
}
private ElementUtils() {}
/**
* Get's the list of members to be put in the VelocityContext.
* Gets the list of members to be put in the VelocityContext.
*
* @param project Project
* @param psi PSI adapter
* @param members a list of {@link com.intellij.psi.PsiMember} objects.
* @return a filtered list of only the fields as {@link FieldElement} objects.
*/
public static List<FieldElement> getOnlyAsFieldElements(Project project, PsiAdapter psi, Collection<PsiMember> members) {
public static List<FieldElement> getOnlyAsFieldElements(Collection<PsiMember> members) {
List<FieldElement> fieldElementList = new ArrayList<FieldElement>();
for (PsiMember member : members) {
if (member instanceof PsiField) {
PsiField field = (PsiField) member;
FieldElement fe = ElementFactory.newFieldElement(project, field, psi);
FieldElement fe = ElementFactory.newFieldElement(field);
fieldElementList.add(fe);
}
}
@@ -57,20 +51,18 @@ public class ElementUtils {
}
/**
* Get's the list of members to be put in the VelocityContext.
* Gets the list of members to be put in the VelocityContext.
*
* @param psi PSI adapter
* @param elementFactory Element Factory
* @param members a list of {@link com.intellij.psi.PsiMember} objects.
* @return a filtered list of only the methods as a {@link MethodElement} objects.
*/
public static List<MethodElement> getOnlyAsMethodElements(PsiElementFactory elementFactory, PsiAdapter psi, Collection<PsiMember> members) {
public static List<MethodElement> getOnlyAsMethodElements(Collection<PsiMember> members) {
List<MethodElement> methodElementList = new ArrayList<MethodElement>();
for (PsiMember member : members) {
if (member instanceof PsiMethod) {
PsiMethod method = (PsiMethod) member;
MethodElement me = ElementFactory.newMethodElement(method, elementFactory, psi);
MethodElement me = ElementFactory.newMethodElement(method);
methodElementList.add(me);
}
}
@@ -79,30 +71,25 @@ public class ElementUtils {
}
/**
* Get's the list of members to be put in the VelocityContext.
* Gets the list of members to be put in the VelocityContext.
*
* @param project Project
* @param elementFactory Element Factory
* @param psi PSI adapter
* @param members a list of {@link com.intellij.psi.PsiMember} objects.
* @return a filtered list of only the methods as a {@link FieldElement} or {@link MethodElement} objects.
*/
public static List<Element> getOnlyAsFieldAndMethodElements(Project project, PsiElementFactory elementFactory, PsiAdapter psi, Collection<PsiMember> members) {
public static List<Element> getOnlyAsFieldAndMethodElements(Collection<PsiMember> members) {
List<Element> elementList = new ArrayList<Element>();
for (PsiMember member : members) {
if (member instanceof PsiField) {
PsiField field = (PsiField) member;
FieldElement fe = ElementFactory.newFieldElement(project, field, psi);
FieldElement fe = ElementFactory.newFieldElement(field);
elementList.add(fe);
} else if (member instanceof PsiMethod) {
PsiMethod method = (PsiMethod) member;
MethodElement me = ElementFactory.newMethodElement(method, elementFactory, psi);
MethodElement me = ElementFactory.newMethodElement(method);
elementList.add(me);
}
}
return elementList;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007 the original author or authors.
* Copyright 2001-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,6 @@
package org.jetbrains.generate.tostring.inspection;
import com.intellij.codeInspection.LocalQuickFix;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import org.jetbrains.generate.tostring.psi.PsiAdapterFactory;
import org.jetbrains.annotations.NotNull;
/**
@@ -25,12 +23,6 @@ import org.jetbrains.annotations.NotNull;
*/
public abstract class AbstractGenerateToStringQuickFix implements LocalQuickFix {
protected PsiAdapter psi;
public AbstractGenerateToStringQuickFix() {
psi = PsiAdapterFactory.getPsiAdapter();
}
@NotNull
public String getName() {
return "Generate toString()";
@@ -25,8 +25,6 @@ import com.intellij.util.ui.CheckBox;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.generate.tostring.GenerateToStringContext;
import org.jetbrains.generate.tostring.GenerateToStringUtils;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import org.jetbrains.generate.tostring.psi.PsiAdapterFactory;
import org.jetbrains.generate.tostring.util.StringUtil;
import javax.swing.*;
@@ -83,8 +81,6 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
if (nameIdentifier == null || clazz.getName() == null)
return;
PsiAdapter psi = PsiAdapterFactory.getPsiAdapter();
// must not be an exception
if (excludeException && InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE)) {
log.debug("This class is an exception");
@@ -130,19 +126,17 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
}
// get list of fields and getter methods supposed to be dumped in the toString method
Project project = clazz.getProject();
fields = GenerateToStringUtils.filterAvailableFields(project, psi, clazz, GenerateToStringContext.getConfig().getFilterPattern());
fields = GenerateToStringUtils.filterAvailableFields(clazz, GenerateToStringContext.getConfig().getFilterPattern());
PsiMethod[] methods = null;
if (GenerateToStringContext.getConfig().isEnableMethods()) {
// okay 'getters in code generation' is enabled so check
methods = GenerateToStringUtils.filterAvailableMethods(psi, clazz, GenerateToStringContext.getConfig().getFilterPattern());
methods = GenerateToStringUtils.filterAvailableMethods(clazz, GenerateToStringContext.getConfig().getFilterPattern());
}
// there should be any fields
if (fields == null && methods == null)
return;
else if (Math.max( fields == null ? 0 : fields.length, methods == null ? 0 : methods.length) == 0)
return;
if (Math.max(fields.length, methods == null ? 0 : methods.length) == 0) {
return;
}
// okay some fields/getter methods are supposed to dumped, does a toString method exist
final PsiMethod[] toStringMethods = clazz.findMethodsByName("toString", false);
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.generate.tostring.GenerateToStringContext;
import org.jetbrains.generate.tostring.GenerateToStringUtils;
import org.jetbrains.generate.tostring.psi.PsiAdapter;
import org.jetbrains.generate.tostring.psi.PsiAdapterFactory;
/**
* Intention to check if the current class toString() method is out of
@@ -80,7 +79,6 @@ public class FieldNotUsedInToStringInspection extends AbstractToStringInspection
}
// must have fields
PsiAdapter psi = PsiAdapterFactory.getPsiAdapter();
PsiField[] fields = clazz.getFields();
if (fields.length == 0) {
log.debug("Class does not have any fields");
@@ -88,7 +86,7 @@ public class FieldNotUsedInToStringInspection extends AbstractToStringInspection
}
// a toString method must exist
PsiMethod toStringMethod = psi.findMethodByName(clazz, "toString");
PsiMethod toStringMethod = PsiAdapter.findMethodByName(clazz, "toString");
if (toStringMethod == null) {
log.debug("No toString() method");
return;
@@ -113,7 +111,7 @@ public class FieldNotUsedInToStringInspection extends AbstractToStringInspection
// get list of fields supposed to be dumped in the toString method
Project project = clazz.getProject();
fields = GenerateToStringUtils.filterAvailableFields(project, psi, clazz, GenerateToStringContext.getConfig().getFilterPattern());
fields = GenerateToStringUtils.filterAvailableFields(clazz, GenerateToStringContext.getConfig().getFilterPattern());
if (fields.length == 0) {
log.debug("No fields to be dumped as all fields was excluded (exclude field by XXX from Settings)");
return;
@@ -159,8 +157,7 @@ public class FieldNotUsedInToStringInspection extends AbstractToStringInspection
}
// a toString method must exist
PsiAdapter psi = PsiAdapterFactory.getPsiAdapter();
PsiMethod toStringMethod = psi.findMethodByName(clazz, "toString");
PsiMethod toStringMethod = PsiAdapter.findMethodByName(clazz, "toString");
if (toStringMethod == null) {
log.debug("No toString() method");
return;
@@ -188,7 +185,7 @@ public class FieldNotUsedInToStringInspection extends AbstractToStringInspection
}
// get list of methods supposed to be dumped in the toString method
methods = GenerateToStringUtils.filterAvailableMethods(psi, clazz, GenerateToStringContext.getConfig().getFilterPattern());
methods = GenerateToStringUtils.filterAvailableMethods(clazz, GenerateToStringContext.getConfig().getFilterPattern());
if (methods.length == 0) {
log.debug("No getter methods to be dumped as all methods was excluded or a field existed for the getter method (exclude method by XXX from Settings)");
return;
@@ -38,7 +38,7 @@ public class GenerateToStringQuickFix extends AbstractGenerateToStringQuickFix {
// execute the action
GenerateToStringActionHandler handler = new GenerateToStringActionHandlerImpl();
handler.executeActionQickFix(project, clazz);
handler.executeActionQuickFix(project, clazz);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2007 the original author or authors.
* Copyright 2001-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,22 +34,18 @@ import org.jetbrains.generate.tostring.util.StringUtil;
*/
public class PsiAdapter {
/**
* Constructor - use {@link PsiAdapterFactory}.
*/
protected PsiAdapter() {
}
private PsiAdapter() {}
/**
/**
* Returns true if a field is constant.
* <p/>
* This is identifed as the name of the field is only in uppercase and it has
* This is identified as the name of the field is only in uppercase and it has
* a <code>static</code> modifier.
*
* @param field field to check if it's a constant
* @return true if constant.
*/
public boolean isConstantField(PsiField field) {
public static boolean isConstantField(PsiField field) {
PsiModifierList list = field.getModifierList();
if (list == null) {
return false;
@@ -65,7 +61,7 @@ public class PsiAdapter {
}
/**
* Find's an existing method with the given name.
* Finds an existing method with the given name.
* If there isn't a method with the name, null is returned.
*
* @param clazz the class
@@ -73,25 +69,26 @@ public class PsiAdapter {
* @return the found method, null if none exist
*/
@Nullable
public PsiMethod findMethodByName(PsiClass clazz, String name) {
public static PsiMethod findMethodByName(PsiClass clazz, String name) {
PsiMethod[] methods = clazz.getMethods();
// use reverse to find from botton as the duplicate conflict resolution policy requires this
// use reverse to find from bottom as the duplicate conflict resolution policy requires this
for (int i = methods.length - 1; i >= 0; i--) {
PsiMethod method = methods[i];
if (name.equals(method.getName()))
if (name.equals(method.getName())) {
return method;
}
}
return null;
}
/**
* Returns true if the given field a primtive array type (e.g., int[], long[], float[]).
* Returns true if the given field a primitive array type (e.g., int[], long[], float[]).
*
* @param type type.
* @return true if field is a primitve array type.
* @return true if field is a primitive array type.
*/
public boolean isPrimitiveArrayType(PsiType type) {
public static boolean isPrimitiveArrayType(PsiType type) {
return type instanceof PsiArrayType && isPrimitiveType(((PsiArrayType) type).getComponentType());
}
@@ -101,7 +98,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's an Object array type.
*/
public boolean isObjectArrayType(PsiType type) {
public static boolean isObjectArrayType(PsiType type) {
return type instanceof PsiArrayType && !isPrimitiveType(((PsiArrayType) type).getComponentType());
}
@@ -111,7 +108,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a String array type.
*/
public boolean isStringArrayType(PsiType type) {
public static boolean isStringArrayType(PsiType type) {
if (isPrimitiveType(type))
return false;
@@ -125,7 +122,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a Collection type.
*/
public boolean isCollectionType(PsiElementFactory factory, PsiType type) {
public static boolean isCollectionType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, "java.util.Collection");
}
@@ -136,7 +133,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a Map type.
*/
public boolean isMapType(PsiElementFactory factory, PsiType type) {
public static boolean isMapType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, CommonClassNames.JAVA_UTIL_MAP);
}
@@ -147,7 +144,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a Map type.
*/
public boolean isSetType(PsiElementFactory factory, PsiType type) {
public static boolean isSetType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, CommonClassNames.JAVA_UTIL_SET);
}
@@ -158,7 +155,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a Map type.
*/
public boolean isListType(PsiElementFactory factory, PsiType type) {
public static boolean isListType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, CommonClassNames.JAVA_UTIL_LIST);
}
@@ -169,7 +166,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a String type.
*/
public boolean isStringType(PsiElementFactory factory, PsiType type) {
public static boolean isStringType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, "java.lang.String");
}
@@ -180,7 +177,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's an Object type.
*/
public boolean isObjectType(PsiElementFactory factory, PsiType type) {
public static boolean isObjectType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, CommonClassNames.JAVA_LANG_OBJECT);
}
@@ -191,7 +188,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a Date type.
*/
public boolean isDateType(PsiElementFactory factory, PsiType type) {
public static boolean isDateType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, "java.util.Date");
}
@@ -202,7 +199,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a Calendar type.
*/
public boolean isCalendarType(PsiElementFactory factory, PsiType type) {
public static boolean isCalendarType(PsiElementFactory factory, PsiType type) {
return isTypeOf(factory, type, "java.util.Calendar");
}
@@ -213,7 +210,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a Boolean or boolean type.
*/
public boolean isBooleanType(PsiElementFactory factory, PsiType type) {
public static boolean isBooleanType(PsiElementFactory factory, PsiType type) {
if (isPrimitiveType(type)) {
// test for simple type of boolean
String s = type.getCanonicalText();
@@ -231,7 +228,7 @@ public class PsiAdapter {
* @param type type.
* @return true if it's a numeric type.
*/
public boolean isNumericType(PsiElementFactory factory, PsiType type) {
public static boolean isNumericType(PsiElementFactory factory, PsiType type) {
if (isPrimitiveType(type)) {
// test for simple type of numeric
String s = type.getCanonicalText();
@@ -242,36 +239,37 @@ public class PsiAdapter {
}
}
/**
/**
* Does the javafile have the import statement?
*
* @param javaFile javafile.
* @param importStatement import statement to test existing for.
* @return true if the javafile has the import statement.
*/
public boolean hasImportStatement(PsiJavaFile javaFile, String importStatement) {
public static boolean hasImportStatement(PsiJavaFile javaFile, String importStatement) {
PsiImportList importList = javaFile.getImportList();
if (importList == null) {
return false;
}
if (importStatement.endsWith(".*")) {
return (importList.findOnDemandImportStatement(fixImportStatement(importStatement)) != null);
return importList.findOnDemandImportStatement(fixImportStatement(importStatement)) != null;
} else {
return (importList.findSingleClassImportStatement(importStatement) != null);
return importList.findSingleClassImportStatement(importStatement) != null;
}
}
/**
* Add's an importstatement to the javafile and optimizes the imports afterwards.
* Adds an import statement to the javafile and optimizes the imports afterwards.
*
*
* @param javaFile javafile.
* @param importStatementOnDemand name of importstatement, must be with a wildcard (etc. java.util.*).
* @param factory PSI element factory.
* @param importStatementOnDemand name of import statement, must be with a wildcard (etc. java.util.*).
* @throws com.intellij.util.IncorrectOperationException
* is thrown if there is an error creating the importstatement.
* is thrown if there is an error creating the import statement.
*/
public void addImportStatement(PsiJavaFile javaFile, String importStatementOnDemand, PsiElementFactory factory) throws IncorrectOperationException {
public static void addImportStatement(PsiJavaFile javaFile, String importStatementOnDemand) {
PsiElementFactory factory = JavaPsiFacade.getInstance(javaFile.getProject()).getElementFactory();
PsiImportStatement is = factory.createImportStatementOnDemand(fixImportStatement(importStatementOnDemand));
// add the import to the file, and optimize the imports
@@ -293,7 +291,7 @@ public class PsiAdapter {
* @param importStatementOnDemand import statement
* @return import statement only with packagename
*/
private String fixImportStatement(String importStatementOnDemand) {
private static String fixImportStatement(String importStatementOnDemand) {
if (importStatementOnDemand.endsWith(".*")) {
return importStatementOnDemand.substring(0, importStatementOnDemand.length() - 2);
} else {
@@ -311,33 +309,14 @@ public class PsiAdapter {
}
/**
* Does this class have a super class?
* <p/>
* If the class just extends java.lang.Object then false is returned.
* Extending java.lang.Object is <b>not</b> concidered the class to have a super class.
*
* @param project the IDEA project
* @param clazz the class to test
* @return true if this class extends another class.
*/
public boolean hasSuperClass(Project project, PsiClass clazz) {
PsiClass superClass = getSuperClass(project, clazz);
if (superClass == null) {
return false;
}
return (!"Object".equals(superClass.getName()));
}
/**
* Get's the fields fully qualified classname (etc java.lang.String, java.util.ArrayList)
* Gets the fields fully qualified classname (etc java.lang.String, java.util.ArrayList)
*
* @param type the type.
* @return the fully qualified classname, null if the field is a primitive.
* @see #getTypeClassName(com.intellij.psi.PsiType) for the non qualified version.
*/
@Nullable
public String getTypeQualifiedClassName(PsiType type) {
public static String getTypeQualifiedClassName(PsiType type) {
if (isPrimitiveType(type)) {
return null;
}
@@ -352,14 +331,14 @@ public class PsiAdapter {
}
/**
* Get's the fields classname (etc. String, ArrayList)
* Gets the fields classname (etc. String, ArrayList)
*
* @param type the type.
* @return the classname, null if the field is a primitive.
* @see #getTypeQualifiedClassName(com.intellij.psi.PsiType) for the qualified version.
*/
@Nullable
public String getTypeClassName(PsiType type) {
public static String getTypeClassName(PsiType type) {
String name = getTypeQualifiedClassName(type);
// return null if it was a primitive type
@@ -371,14 +350,14 @@ public class PsiAdapter {
return name.substring(i + 1, name.length());
}
/**
/**
* Finds the public static void main(String[] args) method.
*
* @param clazz the class.
* @return the method if it exists, null if not.
*/
@Nullable
public PsiMethod findPublicStaticVoidMainMethod(PsiClass clazz) {
public static PsiMethod findPublicStaticVoidMainMethod(PsiClass clazz) {
PsiMethod[] methods = clazz.findMethodsByName("main", false);
// is it public static void main(String[] args)
@@ -395,7 +374,7 @@ public class PsiAdapter {
// must have void as return type
PsiType returnType = method.getReturnType();
if (returnType == null || returnType.equalsToText("void")) {
if (!PsiType.VOID.equals(returnType)) {
continue;
}
@@ -421,8 +400,6 @@ public class PsiAdapter {
/**
* Add or replaces the javadoc comment to the given method.
*
* @param factory element factory.
* @param codeStyleManager CodeStyleManager.
* @param method the method the javadoc should be added/set to.
* @param javadoc the javadoc comment.
* @param replace true if any existing javadoc should be replaced. false will not replace any existing javadoc and thus leave the javadoc untouched.
@@ -430,7 +407,9 @@ public class PsiAdapter {
* @throws IncorrectOperationException is thrown if error adding/replacing the javadoc comment.
*/
@Nullable
public PsiComment addOrReplaceJavadoc(PsiElementFactory factory, CodeStyleManager codeStyleManager, PsiMethod method, String javadoc, boolean replace) throws IncorrectOperationException {
public static PsiComment addOrReplaceJavadoc(PsiMethod method, String javadoc, boolean replace) {
final Project project = method.getProject();
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
PsiComment comment = factory.createCommentFromText(javadoc, null);
// does a method already exists?
@@ -439,6 +418,7 @@ public class PsiAdapter {
if (replace) {
// javadoc already exists, so replace
doc.replace(comment);
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
codeStyleManager.reformat(method); // to reformat javadoc
return comment;
} else {
@@ -448,6 +428,7 @@ public class PsiAdapter {
} else {
// add new javadoc
method.addBefore(comment, method.getFirstChild());
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
codeStyleManager.reformat(method); // to reformat javadoc
return comment;
}
@@ -459,8 +440,8 @@ public class PsiAdapter {
* @param type the type.
* @return true if a void type, false if not.
*/
public boolean isTypeOfVoid(PsiType type) {
return (type != null && type.equalsToText("void"));
public static boolean isTypeOfVoid(PsiType type) {
return type != null && type.equalsToText("void");
}
/**
@@ -469,27 +450,30 @@ public class PsiAdapter {
* The name of the method must start with <code>get</code> or <code>is</code>.
* And if the method is a <code>isXXX</code> then the method must return a java.lang.Boolean or boolean.
*
* @param factory element factory.
*
* @param method the method
* @return true if a getter method, false if not.
*/
public boolean isGetterMethod(PsiElementFactory factory, PsiMethod method) {
public static boolean isGetterMethod(PsiMethod method) {
// must not be a void method
if (isTypeOfVoid(method.getReturnType())) {
return false;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 0) {
return false;
}
if (method.getName().matches("^(is|has)\\p{Upper}.*")) {
return isBooleanType(factory, method.getReturnType());
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(method.getProject());
return isBooleanType(factory, method.getReturnType());
} else if (method.getName().matches("^(get)\\p{Upper}.*")) {
return true;
}
return false;
}
/**
* Get's the field name of the getter method.
* Gets the field name of the getter method.
* <p/>
* The method must be a getter method for a field.
* Returns null if this method is not a getter.
@@ -499,28 +483,27 @@ public class PsiAdapter {
* <p/>
* Example: methodName=getName will return fieldname=name
*
* @param factory element factory.
*
* @param method the method
* @return the fieldname if this is a getter method.
* @see #isGetterMethod(com.intellij.psi.PsiElementFactory,com.intellij.psi.PsiMethod) for the getter check
* @see #isGetterMethod(com.intellij.psi.PsiMethod) for the getter check
*/
@Nullable
public String getGetterFieldName(PsiElementFactory factory, PsiMethod method) {
public static String getGetterFieldName(PsiMethod method) {
// must be a getter
if (!isGetterMethod(factory, method)) {
if (!isGetterMethod(method)) {
return null;
}
return PropertyUtil.getPropertyNameByGetter(method);
}
/**
/**
* Returns true if the field is enum (JDK1.5).
*
* @param field field to check if it's a enum
* @return true if enum.
*/
public boolean isEnumField(PsiField field) {
public static boolean isEnumField(PsiField field) {
PsiType type = field.getType();
// must not be an primitive type
@@ -541,7 +524,7 @@ public class PsiAdapter {
}
return clazz.isEnum();
}
}
/**
* Is the class an exception - extends Throwable (will check super).
@@ -553,14 +536,14 @@ public class PsiAdapter {
return InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE);
}
/**
/**
* Finds the public boolean equals(Object o) method.
*
* @param clazz the class.
* @return the method if it exists, null if not.
*/
@Nullable
public PsiMethod findEqualsMethod(PsiClass clazz) {
public static PsiMethod findEqualsMethod(PsiClass clazz) {
PsiMethod[] methods = clazz.findMethodsByName("equals", false);
// is it public boolean equals(Object o)
@@ -571,13 +554,13 @@ public class PsiAdapter {
}
// must not be static
if (method.hasModifierProperty(PsiModifier.STATIC)) {
continue;
}
if (method.hasModifierProperty(PsiModifier.STATIC)) {
continue;
}
// must have boolean as return type
PsiType returnType = method.getReturnType();
if (returnType == null || !returnType.equalsToText("boolean")) {
if (!PsiType.BOOLEAN.equals(returnType)) {
continue;
}
@@ -607,7 +590,7 @@ public class PsiAdapter {
* @return the method if it exists, null if not.
*/
@Nullable
public PsiMethod findHashCodeMethod(PsiClass clazz) {
public static PsiMethod findHashCodeMethod(PsiClass clazz) {
PsiMethod[] methods = clazz.findMethodsByName("hashCode", false);
// is it public int hashCode()
@@ -618,19 +601,19 @@ public class PsiAdapter {
}
// must not be static
if (method.hasModifierProperty(PsiModifier.STATIC)) {
continue;
}
if (method.hasModifierProperty(PsiModifier.STATIC)) {
continue;
}
// must have int as return type
PsiType returnType = method.getReturnType();
if (returnType == null || !returnType.equalsToText("int")) {
if (!PsiType.INT.equals(returnType)) {
continue;
}
// must not have a parameter
PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != 0) {
PsiParameterList parameters = method.getParameterList();
if (parameters.getParametersCount() != 0) {
continue;
}
@@ -642,39 +625,15 @@ public class PsiAdapter {
return null;
}
/**
* Adds/replaces the given annotation text to the method.
*
* @param factory element factory.
* @param method the method the javadoc should be added/set to.
* @param annotation the annotation as text.
* @return the added annotation object
* @throws IncorrectOperationException is thrown if error adding/replacing the javadoc comment.
*/
public PsiAnnotation addAnnotationToMethod(JVMElementFactory factory, PsiMethod method, String annotation) throws IncorrectOperationException {
PsiAnnotation ann = method.getModifierList().findAnnotation(annotation);
if (ann == null) {
// add new annotation
ann = factory.createAnnotationFromText(annotation, method.getModifierList());
PsiModifierList modifierList = method.getModifierList();
modifierList.addBefore(ann, modifierList.getFirstChild());
} else {
PsiModifierList modifierList = method.getModifierList();
modifierList.replace(ann); // already exist so replace
}
return ann;
}
/**
* Check if the given type against a FQ classname (assignable).
*
* @param factory IDEA factory
* @param type the type
* @param typeFQClassName the FQ classname to test against.
* @return true if the given type is assigneable of FQ classname.
* @return true if the given type is assignable of FQ classname.
*/
protected boolean isTypeOf(PsiElementFactory factory, PsiType type, String typeFQClassName) {
protected static boolean isTypeOf(PsiElementFactory factory, PsiType type, String typeFQClassName) {
// fix for IDEA where fields can have 'void' type and generate NPE.
if (isTypeOfVoid(type)) {
return false;
@@ -693,35 +652,12 @@ public class PsiAdapter {
}
/**
* Get's the superclass.
*
* @param project IDEA project
* @param clazz the class
* @return the super, null if not found.
*/
@Nullable
public PsiClass getSuperClass(Project project, PsiClass clazz) {
PsiReferenceList list = clazz.getExtendsList();
// check if no superclass at all
if (list == null || list.getReferencedTypes().length != 1) {
return null;
}
// have superclass get it [0] is the index of the superclass (a class can not extend more than one class)
GlobalSearchScope scope = list.getReferencedTypes()[0].getResolveScope();
String classname = list.getReferencedTypes()[0].getCanonicalText();
return JavaPsiFacade.getInstance(project).findClass(classname, scope);
}
/**
* Get's the names the given class implements (not FQ names).
* Gets the names the given class implements (not FQ names).
*
* @param clazz the class
* @return the names.
*/
public String[] getImplementsClassnames(PsiClass clazz) {
public static String[] getImplementsClassnames(PsiClass clazz) {
PsiClass[] interfaces = clazz.getInterfaces();
if (interfaces == null || interfaces.length == 0) {
@@ -743,30 +679,30 @@ public class PsiAdapter {
* @param type the type.
* @return true if primitive, false if not.
*/
public boolean isPrimitiveType(PsiType type) {
public static boolean isPrimitiveType(PsiType type) {
return type instanceof PsiPrimitiveType;
}
/**
* Executes the given runable in IDEA command.
* Executes the given runnable in IDEA command.
*
* @param project IDEA project
* @param runable the runable task to exexute.
* @param runnable the runnable task to execute.
*/
public void executeCommand(Project project, Runnable runable) {
CommandProcessor.getInstance().executeCommand(project, runable, "GenerateToString", null);
public static void executeCommand(Project project, Runnable runnable) {
CommandProcessor.getInstance().executeCommand(project, runnable, "GenerateToString", null);
}
/**
* Add's the interface name to the class implementation list.
* Adds the interface name to the class implementation list.
*
* @param project IDEA project
* @param clazz the class
* @param interfaceName the interface name the class should implement
* @throws IncorrectOperationException is thrown by IDEA.
*/
public void addImplements(Project project, PsiClass clazz, String interfaceName) throws IncorrectOperationException {
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
public static void addImplements(PsiClass clazz, String interfaceName) {
final Project project = clazz.getProject();
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
// get the interface class
PsiClass interfaceClass = facade.findClass(interfaceName, GlobalSearchScope.allScope(project));
@@ -1,43 +0,0 @@
/*
* Copyright 2001-2007 the original author or authors.
*
* 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.generate.tostring.psi;
/**
* Factory to get a PsiAdapter class compatible with the correct version of IDEA.
*
* @see PsiAdapter
*/
public class PsiAdapterFactory {
private static PsiAdapter instance; // singleton instance
private PsiAdapterFactory() {
}
/**
* Gets the PsiAdapter
*
* @return the PsiAdapter used for the current version of IDEA.
*/
public static PsiAdapter getPsiAdapter() {
if (instance == null) {
instance = new PsiAdapter();
}
return instance;
}
}
@@ -17,9 +17,9 @@ package org.jetbrains.idea.maven.dom.inspections;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.Processor;
import com.intellij.util.containers.hash.HashSet;
@@ -65,8 +65,14 @@ public class MavenDuplicateDependenciesInspection extends BasicDomElementsInspec
for (MavenDomDependency d : dependencies) {
if (d == dependency) continue;
if (d.getParent() == dependency.getParent() || scope(d).equals(scope(dependency))) {
duplicatedDependencies.add(d);
if (d.getParent() == dependency.getParent()) {
duplicatedDependencies.add(d); // Dependencies in same file must be unique by groupId:artifactId:type:classifier
}
else {
if (scope(d).equals(scope(dependency))
&& Comparing.equal(d.getVersion().getStringValue(), dependency.getVersion().getStringValue())) {
duplicatedDependencies.add(d); // Dependencies in same file must be unique by groupId:artifactId:VERSION:type:classifier:SCOPE
}
}
}
@@ -176,11 +182,10 @@ public class MavenDuplicateDependenciesInspection extends BasicDomElementsInspec
if (StringUtil.isEmptyOrSpaces(groupId) || StringUtil.isEmptyOrSpaces(artifactId)) return null;
String version = coordinates.getVersion().getStringValue();
String type = coordinates.getType().getStringValue();
String classifier = coordinates.getClassifier().getStringValue();
return groupId + ":" + artifactId + ":" + version + ":" + type + ":" + classifier;
return groupId + ":" + artifactId + ":" + type + ":" + classifier;
}
@NotNull
@@ -23,7 +23,7 @@ import org.jetbrains.idea.maven.dom.inspections.MavenDuplicateDependenciesInspec
*/
class MavenDuplicatedInspectionTest extends MavenDomTestCase {
public void testDuplicatedInOneFile() {
public void testDuplicatedInSameFile() {
myFixture.enableInspections(MavenDuplicateDependenciesInspection)
createProjectPom("""
@@ -49,7 +49,32 @@ class MavenDuplicatedInspectionTest extends MavenDomTestCase {
checkHighlighting()
}
public void testDuplicatedInParent1() {
public void testDuplicatedInSameFileDifferentVersion() {
myFixture.enableInspections(MavenDuplicateDependenciesInspection)
createProjectPom("""
<groupId>mavenParent</groupId>
<artifactId>childA</artifactId>
<version>1.0</version>
<dependencies>
<<warning>dependency</warning>>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
</dependency>
<<warning>dependency</warning>>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
</dependency>
</dependencies>
""")
checkHighlighting()
}
public void testDuplicatedInParentDifferentScope() {
myFixture.enableInspections(MavenDuplicateDependenciesInspection)
createModulePom("child", """
@@ -98,7 +123,7 @@ class MavenDuplicatedInspectionTest extends MavenDomTestCase {
checkHighlighting(myProjectPom, true, false, true)
}
public void testDuplicatedInParent2() {
public void testDuplicatedInParentSameScope() {
myFixture.enableInspections(MavenDuplicateDependenciesInspection)
createModulePom("child", """
@@ -146,4 +171,49 @@ class MavenDuplicatedInspectionTest extends MavenDomTestCase {
checkHighlighting(myProjectPom, true, false, true)
}
public void testDuplicatedInParentDifferentVersion() {
myFixture.enableInspections(MavenDuplicateDependenciesInspection)
createModulePom("child", """
<groupId>mavenParent</groupId>
<artifactId>child</artifactId>
<version>1.0</version>
<parent>
<groupId>mavenParent</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
</dependency>
</dependencies>
""")
importProject("""
<groupId>mavenParent</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>child</module>
</modules>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
</dependency>
</dependencies>
""")
checkHighlighting(myProjectPom, true, false, true)
}
}