<module fileurl="file://$PROJECT_DIR$/platform/forms_rt/forms_rt.iml" filepath="$PROJECT_DIR$/platform/forms_rt/forms_rt.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/generate-tostring/generate-tostring.iml" filepath="$PROJECT_DIR$/plugins/generate-tostring/generate-tostring.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/git4idea/git4idea.iml" filepath="$PROJECT_DIR$/plugins/git4idea/git4idea.iml" group="plugins/VCS" />
- <module fileurl="file://$PROJECT_DIR$/plugins/groovy/grape/grape.iml" filepath="$PROJECT_DIR$/plugins/groovy/grape/grape.iml" group="plugins/Groovy" />
- <module fileurl="file://$PROJECT_DIR$/plugins/groovy/grape/grape-rt.iml" filepath="$PROJECT_DIR$/plugins/groovy/grape/grape-rt.iml" group="plugins/Groovy" />
- <module fileurl="file://$PROJECT_DIR$/plugins/groovy/hotswap/groovy-hotswap.iml" filepath="$PROJECT_DIR$/plugins/groovy/hotswap/groovy-hotswap.iml" group="plugins/Groovy" />
- <module fileurl="file://$PROJECT_DIR$/plugins/groovy/rt/groovy-rt.iml" filepath="$PROJECT_DIR$/plugins/groovy/rt/groovy-rt.iml" group="plugins/Groovy" />
- <module fileurl="file://$PROJECT_DIR$/plugins/groovy/groovypp/groovypp.iml" filepath="$PROJECT_DIR$/plugins/groovy/groovypp/groovypp.iml" group="plugins/Groovy" />
<module fileurl="file://$PROJECT_DIR$/plugins/hg4idea/hg4idea.iml" filepath="$PROJECT_DIR$/plugins/hg4idea/hg4idea.iml" group="plugins/VCS" />
<module fileurl="file://$PROJECT_DIR$/platform/icons/icons.iml" filepath="$PROJECT_DIR$/platform/icons/icons.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/java/idea-ui/idea-ui.iml" filepath="$PROJECT_DIR$/java/idea-ui/idea-ui.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/compiler/javac2/javac2.iml" filepath="$PROJECT_DIR$/java/compiler/javac2/javac2.iml" group="java/compiler" />
<module fileurl="file://$PROJECT_DIR$/plugins/cvs/javacvs-src/javacvs-src.iml" filepath="$PROJECT_DIR$/plugins/cvs/javacvs-src/javacvs-src.iml" group="plugins/VCS/cvs" />
<module fileurl="file://$PROJECT_DIR$/plugins/groovy/jetgroovy.iml" filepath="$PROJECT_DIR$/plugins/groovy/jetgroovy.iml" group="plugins/Groovy" />
- <module fileurl="file://$PROJECT_DIR$/plugins/groovy/jetgroovy-tests.iml" filepath="$PROJECT_DIR$/plugins/groovy/jetgroovy-tests.iml" group="plugins/Groovy" />
<module fileurl="file://$PROJECT_DIR$/java/jsp-base-openapi/jsp-base-openapi.iml" filepath="$PROJECT_DIR$/java/jsp-base-openapi/jsp-base-openapi.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" filepath="$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/jsp-spi/jsp-spi.iml" filepath="$PROJECT_DIR$/java/jsp-spi/jsp-spi.iml" group="java" />
layoutPlugin("SpellChecker", "spellchecker", "spellchecker-core")
layoutPlugin("RelaxNG-Support", "relaxng") {
- fileset(dir: "${home}/community/plugins/relaxng/lib", includes: "**/*.jar")
+ fileset(dir: "$home/plugins/relaxng/lib", includes: "**/*.jar")
}
layoutPlugin("maven") {
dir("standardDsls") {
fileset(dir: "$home/plugins/groovy/resources/standardDsls")
}
+ dir("agent") {
+ fileset(dir: "${home}/plugins/groovy/hotswap") {
+ include(name: "gragent.jar")
+ }
+ }
+
fileset(dir: "$home/plugins/groovy/resources/conf")
fileset(dir: "${home}/plugins/groovy/lib")
}
}
- dir("Groovypp") {
- dir("lib") {
- jar("groovypp.jar") {
- module("groovypp")
- }
- }
- }
-
}
}
synchronized (mySourcesToRecompile) {
final TIntHashSet pathsToRecompile = mySourcesToRecompile.get(projectId);
if (_forceCompile || pathsToRecompile != null && !pathsToRecompile.isEmpty()) {
+ if (ourDebugMode) {
+ System.out.println("Analysing potentially recompilable files for " + compiler.getDescription());
+ }
while (scopeSrcIterator.hasNext()) {
final VirtualFile file = scopeSrcIterator.next();
if (!file.isValid()) {
if (LOG.isDebugEnabled() || ourDebugMode) {
- final String message = "Skipping invalid file " + file.getPresentableUrl();
- LOG.debug(message);
+ LOG.debug("Skipping invalid file " + file.getPresentableUrl());
if (ourDebugMode) {
- System.out.println(message);
+ System.out.println("\t SKIPPED(INVALID) " + file.getPresentableUrl());
}
}
continue;
if (_forceCompile) {
if (compiler.isCompilableFile(file, context) && !configuration.isExcludedFromCompilation(file)) {
toCompile.add(file);
+ if (ourDebugMode) {
+ System.out.println("\t INCLUDED " + file.getPresentableUrl());
+ }
selectedForRecompilation.add(file);
if (pathsToRecompile == null || !pathsToRecompile.contains(fileId)) {
addSourceForRecompilation(projectId, file, null);
}
}
+ else {
+ if (ourDebugMode) {
+ System.out.println("\t NOT COMPILABLE OR EXCLUDED " + file.getPresentableUrl());
+ }
+ }
}
else if (pathsToRecompile.contains(fileId)) {
if (compiler.isCompilableFile(file, context) && !configuration.isExcludedFromCompilation(file)) {
toCompile.add(file);
+ if (ourDebugMode) {
+ System.out.println("\t INCLUDED " + file.getPresentableUrl());
+ }
selectedForRecompilation.add(file);
}
+ else {
+ if (ourDebugMode) {
+ System.out.println("\t NOT COMPILABLE OR EXCLUDED " + file.getPresentableUrl());
+ }
+ }
+ }
+ else {
+ if (ourDebugMode) {
+ System.out.println("\t NOT INCLUDED " + file.getPresentableUrl());
+ }
}
}
}
import org.jetbrains.annotations.NonNls;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
public class RemoteConnection {
private boolean myUseSockets;
private boolean myServerMode;
catch (NumberFormatException e) {
}
if (serverMode) {
- result = "-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=" +
- ((p == -1)? "..." : Integer.toString(p)) +
+ String localHostName = "<host name>:";
+ try {
+ final InetAddress localAddress = InetAddress.getLocalHost();
+ final String name = localAddress.getCanonicalHostName();
+ if (name != null) {
+ localHostName = name + ":";
+ }
+ }
+ catch (UnknownHostException e) {
+ }
+ result = "-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=" + localHostName +
+ ((p == -1)? "<port>" : Integer.toString(p)) +
ONTHROW + ",suspend=y" + ONUNCAUGHT;
}
else {
import com.intellij.psi.*;
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
import com.intellij.psi.util.PsiTypesUtil;
+import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
+import java.util.Arrays;
+import java.util.Comparator;
+
public class CreateConstructorParameterFromFieldFix implements IntentionAction {
private final SmartPsiElementPointer<PsiField> myField;
aClass = getField().getContainingClass();
constructors = aClass.getConstructors();
}
- for (int i = 0; i < constructors.length; i++){
- if (!addParameterToConstructor(project, file, editor, getField().getContainingClass().getConstructors()[i])) break;
+ Arrays.sort(constructors, new Comparator<PsiMethod>() {
+ @Override
+ public int compare(PsiMethod c1, PsiMethod c2) {
+ final PsiMethod cc1 = RefactoringUtil.getChainedConstructor(c1);
+ final PsiMethod cc2 = RefactoringUtil.getChainedConstructor(c2);
+ if (cc1 == c2) return 1;
+ if (cc2 == c1) return -1;
+ if (cc1 == null) {
+ return cc2 == null ? 0 : compare(c1, cc2);
+ } else {
+ return cc2 == null ? compare(cc1, c2) : compare(cc1, cc2);
+ }
+ }
+ });
+ for (PsiMethod constructor : constructors) {
+ if (!addParameterToConstructor(project, file, editor, constructor)) break;
}
}
generateTypeParametersSection(buffer, result);
}
+ @Nullable
private static Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findInHierarchy(PsiClass psiClass, final DocTagLocator<PsiDocTag> locator) {
+ final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> inClassComment = findInClassComment(psiClass, locator);
+ if (inClassComment != null) return inClassComment;
for (final PsiClass superClass : psiClass.getSupers()) {
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> pair = findInClassComment(superClass, locator);
if (pair != null) return pair;
final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> pair = findInClassComment(superInterface, locator);
if (pair != null) return pair;
}
- return findInClassComment(psiClass, locator);
+ return null;
}
private static Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findInClassComment(final PsiClass psiClass, final DocTagLocator<PsiDocTag> locator) {
package com.intellij.codeInspection.suspiciousNameCombination;
-import com.intellij.CommonBundle;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.ui.AddDeleteListPanel;
+import com.intellij.ui.AddEditDeleteListPanel;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
}
}
- private class MyOptionsPanel extends AddDeleteListPanel {
- private JButton myEditButton;
+ private class MyOptionsPanel extends AddEditDeleteListPanel<String> {
public MyOptionsPanel() {
super(InspectionsBundle.message("suspicious.name.combination.options.title"), myNameGroups);
- myEditButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- editSelectedItem();
- }
- });
- myList.addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
- editSelectedItem();
- }
- }
- });
myListModel.addListDataListener(new ListDataListener() {
public void intervalAdded(ListDataEvent e) {
saveChanges();
});
}
- @Override protected JButton[] createButtons() {
- myEditButton = new JButton(CommonBundle.message("button.edit"));
- return new JButton[] { myAddButton, myEditButton, myDeleteButton };
- }
-
- protected Object findItemToAdd() {
+ protected String findItemToAdd() {
return Messages.showInputDialog(this,
InspectionsBundle.message("suspicious.name.combination.options.prompt"),
InspectionsBundle.message("suspicious.name.combination.add.titile"),
Messages.getQuestionIcon(), "", null);
}
- private void editSelectedItem() {
- int index = myList.getSelectedIndex();
- if (index >= 0) {
- String inputValue = (String) myListModel.get(index);
- String newValue = Messages.showInputDialog(this,
- InspectionsBundle.message("suspicious.name.combination.options.prompt"),
- InspectionsBundle.message("suspicious.name.combination.edit.title"),
- Messages.getQuestionIcon(),
- inputValue, null);
- if (newValue != null) {
- myListModel.set(index, newValue);
- }
- }
+ @Override
+ protected String editSelectedItem(String inputValue) {
+ return Messages.showInputDialog(this,
+ InspectionsBundle.message("suspicious.name.combination.options.prompt"),
+ InspectionsBundle.message("suspicious.name.combination.edit.title"),
+ Messages.getQuestionIcon(),
+ inputValue, null);
}
private void saveChanges() {
correctedOffset = offset;
}
else if (!Character.isJavaIdentifierPart(text.charAt(correctedOffset))) {
+ if (text.charAt(correctedOffset) == ';') {//initially caret on the end of line
+ correctedOffset--;
+ }
if (text.charAt(correctedOffset) != ')') {
correctedOffset = offset;
}
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PropertyUtil;
-import org.jetbrains.annotations.Nullable;
+import com.intellij.refactoring.util.RefactoringUtil;
import java.util.Map;
initParameterData(parameter, result);
}
- final PsiMethod chainedConstructor = getChainedConstructor(constructor);
+ final PsiMethod chainedConstructor = RefactoringUtil.getChainedConstructor(constructor);
if (chainedConstructor != null) {
final PsiCodeBlock constructorBody = constructor.getBody();
LOG.assertTrue(constructorBody != null);
}
}
- @Nullable
- public static PsiMethod getChainedConstructor(PsiMethod constructor) {
- final PsiCodeBlock constructorBody = constructor.getBody();
- LOG.assertTrue(constructorBody != null);
- final PsiStatement[] statements = constructorBody.getStatements();
- if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
- final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
- if (expression instanceof PsiMethodCallExpression) {
- final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
- final PsiReferenceExpression methodExpr = methodCallExpression.getMethodExpression();
- if ("this".equals(methodExpr.getReferenceName())) {
- return (PsiMethod)methodExpr.resolve();
- }
- }
- }
- return null;
- }
-
private static ParameterData initParameterData(PsiParameter parameter, Map<String, ParameterData> result) {
JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(parameter.getProject());
final String paramName = parameter.getName();
import com.intellij.refactoring.replaceConstructorWithBuilder.usageInfo.ReplaceConstructorWithSettersChainInfo;
import com.intellij.refactoring.util.FixableUsageInfo;
import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
+import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.util.IncorrectOperationException;
if (myConstructors.length == 1) return myConstructors[0];
PsiMethod commonConstructor = null;
for (PsiMethod constructor : myConstructors) {
- final PsiMethod chainedConstructor = ParameterData.getChainedConstructor(constructor);
+ final PsiMethod chainedConstructor = RefactoringUtil.getChainedConstructor(constructor);
if (chainedConstructor == null) {
if (commonConstructor != null) {
if (!isChained(commonConstructor, constructor)) {
private static boolean isChained(PsiMethod first, PsiMethod last) {
if (first == null) return false;
if (first == last) return true;
- return isChained(ParameterData.getChainedConstructor(first), last);
+ return isChained(RefactoringUtil.getChainedConstructor(first), last);
}
private String createMethodName() {
*/
package com.intellij.refactoring.util;
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
final PsiMember member,
@Nullable final PsiClass qualifyingClass) throws IncorrectOperationException {
PsiManager manager = referenceExpression.getManager();
+ PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(referenceExpression, PsiMethodCallExpression.class, true);
+ while ((methodCallExpression) != null) {
+ if (HighlightUtil.isSuperOrThisMethodCall(methodCallExpression)) {
+ return referenceExpression;
+ }
+ methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression.class, true);
+ }
PsiReferenceExpression expressionFromText;
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
if (qualifyingClass == null) {
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.introduceField.ElementToWorkOn;
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
+import com.intellij.refactoring.replaceConstructorWithBuilder.ParameterData;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
return array;
}
+ @Nullable
+ public static PsiMethod getChainedConstructor(PsiMethod constructor) {
+ final PsiCodeBlock constructorBody = constructor.getBody();
+ LOG.assertTrue(constructorBody != null);
+ final PsiStatement[] statements = constructorBody.getStatements();
+ if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
+ final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
+ if (expression instanceof PsiMethodCallExpression) {
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+ final PsiReferenceExpression methodExpr = methodCallExpression.getMethodExpression();
+ if ("this".equals(methodExpr.getReferenceName())) {
+ return (PsiMethod)methodExpr.resolve();
+ }
+ }
+ }
+ return null;
+ }
+
public static interface ImplicitConstructorUsageVisitor {
void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor);
--- /dev/null
+// "Add constructor parameter" "true"
+class A {
+ private final int field;
+ private int j;
+
+ A(int field) {
+ this(0, field);
+ }
+
+ A(int j, int field) {
+ this.j = j;
+ this.field = field;
+ }
+}
\ No newline at end of file
--- /dev/null
+// "Add constructor parameter" "true"
+class A {
+ private final int <caret>field;
+ private int j;
+
+ A() {
+ this(0);
+ }
+
+ A(int j) {
+ this.j = j;
+ }
+}
\ No newline at end of file
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
String message = e.getMessage();
assertTrue(message, message.startsWith("local variable <b><code>varName</code></b> has 1 usage that is not safe to delete.\n" +
- "Of those 0 usages are in strings, comments, or non-Java files."));
+ "Of those 0 usages are in strings, comments, or non-code files."));
}
}
-package com.intellij.execution;
+package com.intellij.execution.console;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.VerticalFlowLayout;
-import com.intellij.ui.AddDeleteListPanel;
+import com.intellij.ui.AddEditDeleteListPanel;
import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
private JPanel myMainComponent;
private MyAddDeleteListPanel myPositivePanel;
private MyAddDeleteListPanel myNegativePanel;
- private final ConsoleFoldingSettings mySettings;
-
- public ConsoleFoldingConfigurable(ConsoleFoldingSettings settings) {
- mySettings = settings;
- }
+ private final ConsoleFoldingSettings mySettings = ConsoleFoldingSettings.getSettings();
public JComponent createComponent() {
if (myMainComponent == null) {
return myMainComponent;
}
+ public void addRule(@NotNull String rule) {
+ myPositivePanel.addRule(rule);
+ }
+
public boolean isModified() {
return !Arrays.asList(myNegativePanel.getListItems()).equals(mySettings.getNegativePatterns()) ||
!Arrays.asList(myPositivePanel.getListItems()).equals(mySettings.getPositivePatterns());
myPositivePanel = null;
}
+ @NotNull
public String getId() {
return getDisplayName();
}
return null;
}
- private static class MyAddDeleteListPanel extends AddDeleteListPanel {
+ private static class MyAddDeleteListPanel extends AddEditDeleteListPanel<String> {
private final String myQuery;
public MyAddDeleteListPanel(String title, String query) {
- super(title, new ArrayList());
+ super(title, new ArrayList<String>());
myQuery = query;
}
@Override
@Nullable
- protected Object findItemToAdd() {
- return Messages.showInputDialog(this, myQuery,
- "Folding pattern",
- Messages.getQuestionIcon(), "", null);
+ protected String findItemToAdd() {
+ return showEditDialog("");
+ }
+
+ @Nullable
+ private String showEditDialog(final String initialValue) {
+ return Messages.showInputDialog(this, myQuery, "Folding pattern", Messages.getQuestionIcon(), initialValue, null);
}
void resetFrom(List<String> patterns) {
patterns.add((String)o);
}
}
+
+ public void addRule(String rule) {
+ addElement(rule);
+ }
+
+ @Override
+ protected String editSelectedItem(String item) {
+ return showEditDialog(item);
+ }
}
}
-package com.intellij.execution;
+package com.intellij.execution.console;
import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.util.containers.CollectionFactory;
}
}
+ public static ConsoleFoldingSettings getSettings() {
+ return ServiceManager.getService(ConsoleFoldingSettings.class);
+ }
+
public boolean shouldFoldLine(String line) {
return containsAny(line, myPositivePatterns) && !containsAny(line, myNegativePatterns);
}
-package com.intellij.execution;
+package com.intellij.execution.console;
import com.intellij.openapi.extensions.AbstractExtensionPointBean;
import com.intellij.openapi.extensions.ExtensionPointName;
--- /dev/null
+package com.intellij.execution.console;
+
+import com.intellij.execution.impl.ConsoleViewImpl;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author peter
+ */
+public class FoldLinesLikeThis extends DumbAwareAction {
+ private final Editor myEditor;
+ private final ConsoleViewImpl myConsole;
+
+ public FoldLinesLikeThis(Editor editor, ConsoleViewImpl console) {
+ super("Fold lines like this");
+ myEditor = editor;
+ myConsole = console;
+ }
+
+ @Nullable
+ private String getSingleLineSelection() {
+ final SelectionModel model = myEditor.getSelectionModel();
+ final Document document = myEditor.getDocument();
+ if (!model.hasSelection()) {
+ final int offset = myEditor.getCaretModel().getOffset();
+ if (offset <= document.getTextLength()) {
+ final int lineNumber = document.getLineNumber(offset);
+ final String line = document.getText().substring(document.getLineStartOffset(lineNumber), document.getLineEndOffset(lineNumber)).trim();
+ if (StringUtil.isNotEmpty(line)) {
+ return line;
+ }
+ }
+
+ return null;
+ }
+ final int start = model.getSelectionStart();
+ final int end = model.getSelectionEnd();
+ if (document.getLineNumber(start) == document.getLineNumber(end)) {
+ final String selection = document.getText().substring(start, end).trim();
+ if (StringUtil.isNotEmpty(selection)) {
+ return selection;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ final boolean enabled = getSingleLineSelection() != null;
+ e.getPresentation().setEnabled(enabled);
+ e.getPresentation().setVisible(enabled);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final String selection = getSingleLineSelection();
+ assert selection != null;
+ ShowSettingsUtil.getInstance().editConfigurable(myEditor.getProject(), new ConsoleFoldingConfigurable() {
+ @Override
+ public void reset() {
+ super.reset();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ public void run() {
+ addRule(selection);
+ }
+ }, ModalityState.stateForComponent(createComponent()));
+ }
+ });
+ myConsole.foldImmediately();
+ }
+}
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.TextEditor;
+import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileTypes.FileType;
private final AtomicBoolean myForceScrollToEnd = new AtomicBoolean(false);
private final MergingUpdateQueue myUpdateQueue;
private Runnable myUiUpdateRunnable;
- private boolean myEditorVisible = true;
+ private Editor myFullEditor;
public LanguageConsoleImpl(final Project project, String title, final Language language) {
myProject = project;
});
}
- public void setEditorVisible(boolean visible) {
- if (myEditorVisible == visible) return;
- if (visible) {
+ public void setFullEditorMode(boolean fullEditorMode) {
+ if (myFullEditor != null == fullEditorMode) return;
+ final VirtualFile virtualFile = myFile.getVirtualFile();
+ assert virtualFile != null;
+ final FileEditorManagerEx fileManager = FileEditorManagerEx.getInstanceEx(getProject());
+ if (!fullEditorMode) {
+ fileManager.closeFile(virtualFile);
+ myFullEditor = null;
myPanel.removeAll();
myPanel.add(myHistoryViewer.getComponent(), BorderLayout.NORTH);
myPanel.add(myConsoleEditor.getComponent(), BorderLayout.CENTER);
else {
myPanel.removeAll();
myPanel.add(myHistoryViewer.getComponent(), BorderLayout.CENTER);
+ myFullEditor = fileManager.openTextEditor(new OpenFileDescriptor(getProject(), virtualFile, 0), true);
+ assert myFullEditor != null;
+ fileManager.getCurrentWindow().setFilePinned(virtualFile, true);
}
- myEditorVisible = visible;
}
private void setupComponents() {
printToHistory(text, attributes);
}
+ public Editor getFullEditor() {
+ return myFullEditor;
+ }
+
public void printToHistory(String text, final TextAttributes attributes) {
text = StringUtil.convertLineSeparators(text);
final boolean scrollToEnd = shouldScrollHistoryToEnd();
}
private void updateSizes(boolean forceScrollToEnd) {
- if (!myEditorVisible) return;
+ if (myFullEditor != null) return;
final Dimension panelSize = myPanel.getSize();
final Dimension historyContentSize = myHistoryViewer.getContentSize();
final Dimension contentSize = myConsoleEditor.getContentSize();
if (prevFile != null) {
final FileEditorManager editorManager = FileEditorManager.getInstance(getProject());
final VirtualFile file = prevFile.getVirtualFile();
- if (file != null && editorManager.isFileOpen(file)) {
+ if (file != null && myFullEditor != null) {
+ myFullEditor = null;
final FileEditor prevEditor = editorManager.getSelectedEditor(file);
final boolean focusEditor;
final int offset;
offset = 0;
}
editorManager.closeFile(file);
- editorManager.openTextEditor(new OpenFileDescriptor(getProject(), newVFile, offset), focusEditor);
+ myFullEditor = editorManager.openTextEditor(new OpenFileDescriptor(getProject(), newVFile, offset), focusEditor);
+ ((FileEditorManagerEx)editorManager).getCurrentWindow().setFilePinned(newVFile, true);
}
}
}
-package com.intellij.execution;
+package com.intellij.execution.console;
+
+import com.intellij.execution.ConsoleFolding;
import java.util.List;
import com.intellij.codeInsight.navigation.IncrementalSearchHandler;
import com.intellij.execution.ConsoleFolding;
import com.intellij.execution.ExecutionBundle;
+import com.intellij.execution.console.FoldLinesLikeThis;
import com.intellij.execution.filters.*;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.ConsoleView;
myEditor.getCaretModel().moveToOffset(myEditor.getDocument().getTextLength());
}
+ public void foldImmediately() {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (myFlushAlarm.getActiveRequestCount() > 0) {
+ myFlushAlarm.cancelAllRequests();
+ myFlushDeferredRunnable.run();
+ }
+
+ myFoldingAlarm.cancelAllRequests();
+
+ myPendingFoldRegions.clear();
+ final FoldingModel model = myEditor.getFoldingModel();
+ model.runBatchFoldingOperation(new Runnable() {
+ public void run() {
+ for (FoldRegion region : model.getAllFoldRegions()) {
+ model.removeFoldRegion(region);
+ }
+ }
+ });
+
+ updateFoldings(0, myEditor.getDocument().getLineCount() - 1, true);
+ }
+
private static class TokenInfo{
private final ConsoleViewContentType contentType;
private int startOffset;
final DefaultActionGroup group = new DefaultActionGroup();
group.add(new ClearAllAction());
group.add(new CopyAction());
+ group.add(new FoldLinesLikeThis(myEditor, this));
group.addSeparator();
final ActionManager actionManager = ActionManager.getInstance();
group.add(actionManager.getAction(DiffActions.COMPARE_WITH_CLIPBOARD));
ApplicationManager.getApplication().assertIsDispatchThread();
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
highlightHyperlinks(myEditor, myHyperlinks, myCustomFilter, myPredefinedMessageFilter, line1, endLine);
- updateFoldings(line1, endLine);
+ updateFoldings(line1, endLine, false);
}
- private void updateFoldings(final int line1, final int endLine) {
+ private void updateFoldings(final int line1, final int endLine, boolean immediately) {
final Document document = myEditor.getDocument();
final CharSequence chars = document.getCharsSequence();
final int startLine = Math.max(0, line1);
addFolding(document, chars, line, toAdd);
}
if (!toAdd.isEmpty()) {
- doUpdateFolding(toAdd);
+ doUpdateFolding(toAdd, immediately);
}
}
}
}
- private void doUpdateFolding(final List<FoldRegion> toAdd) {
+ private void doUpdateFolding(final List<FoldRegion> toAdd, final boolean immediately) {
assertIsDispatchThread();
myPendingFoldRegions.addAll(toAdd);
public void run() {
assertIsDispatchThread();
final FoldingModel model = myEditor.getFoldingModel();
- model.runBatchFoldingOperationDoNotCollapseCaret(new Runnable() {
+ final Runnable operation = new Runnable() {
public void run() {
assertIsDispatchThread();
for (FoldRegion region : myPendingFoldRegions) {
}
myPendingFoldRegions.clear();
}
- });
+ };
+ if (immediately) {
+ model.runBatchFoldingOperation(operation);
+ } else {
+ model.runBatchFoldingOperationDoNotCollapseCaret(operation);
+ }
}
};
- if (myPendingFoldRegions.size() > 100) {
+ if (immediately || myPendingFoldRegions.size() > 100) {
runnable.run();
} else {
myFoldingAlarm.addRequest(runnable, 50);
import java.awt.event.KeyEvent;
import java.net.URL;
import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
class RunConfigurable extends BaseConfigurable {
private static final Icon ICON = IconLoader.getIcon("/general/configurableRunDebug.png");
}
}
- private static String createUniqueName(DefaultMutableTreeNode typeNode) {
- String str = ExecutionBundle.message("run.configuration.unnamed.name.prefix");
+ private static String createUniqueName(DefaultMutableTreeNode typeNode, @Nullable String baseName) {
+ String str = (baseName == null) ? ExecutionBundle.message("run.configuration.unnamed.name.prefix") : baseName;
final ArrayList<String> currentNames = new ArrayList<String>();
for (int i = 0; i < typeNode.getChildCount(); i++) {
final Object userObject = ((DefaultMutableTreeNode)typeNode.getChildAt(i)).getUserObject();
}
}
if (!currentNames.contains(str)) return str;
+
+ final Matcher matcher = Pattern.compile("(.*?)\\s*\\(\\d+\\)").matcher(str);
+ final String originalName = (matcher.matches()) ? matcher.group(1) : str;
int i = 1;
while (true) {
- if (!currentNames.contains(str + i)) return str + i;
+ final String newName = String.format("%s (%d)", originalName, i);
+ if (!currentNames.contains(newName)) return newName;
i++;
}
}
sortTree(myRoot);
((DefaultTreeModel)myTree.getModel()).reload();
}
- final RunnerAndConfigurationSettings settings = getRunManager().createConfiguration(createUniqueName(node), factory);
+ final RunnerAndConfigurationSettings settings = getRunManager().createConfiguration(createUniqueName(node, null), factory);
if (factory instanceof ConfigurationFactoryEx) {
((ConfigurationFactoryEx)factory).onNewConfigurationCreated(settings.getConfiguration());
}
try {
final DefaultMutableTreeNode typeNode = getSelectedConfigurationTypeNode();
final RunnerAndConfigurationSettings settings = configuration.getSnapshot();
- final String copyName = createUniqueName(typeNode);
+ final String copyName = createUniqueName(typeNode, configuration.getNameText());
settings.setName(copyName);
final ConfigurationFactory factory = settings.getFactory();
if (factory instanceof ConfigurationFactoryEx) {
return true;//CommonRefactoringUtil.checkReadOnlyStatus(project, element);
}
- private static void showErrorMessage(Project project, Editor editor, String message) {
+ private static void showErrorMessage(Project project, @Nullable Editor editor, String message) {
CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("rename.title"), null);
}
return null;
}
+ /**
+ * Builds the complete set of elements to be renamed during the refactoring.
+ *
+ * @param element the base element for the refactoring.
+ * @param newName the name into which the element is being renamed.
+ * @param allRenames the map (from element to its new name) into which all additional elements to be renamed should be stored.
+ */
public void prepareRenaming(final PsiElement element, final String newName, final Map<PsiElement, String> allRenames) {
}
}
}
+ /**
+ * Returns the element to be renamed instead of the element on which the rename refactoring was invoked (for example, a super method
+ * of an inherited method).
+ *
+ * @param element the element on which the refactoring was invoked.
+ * @param editor the editor in which the refactoring was invoked.
+ * @return the element to rename, or null if the rename refactoring should be canceled.
+ */
@Nullable
- public PsiElement substituteElementToRename(final PsiElement element, Editor editor) {
+ public PsiElement substituteElementToRename(final PsiElement element, @Nullable Editor editor) {
return element;
}
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.TextConsoleBuilder;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
+import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.ExecutionConsole;
public static void printStacktrace(final ConsoleView consoleView, final String unscrambledTrace) {
consoleView.clear();
consoleView.print(unscrambledTrace+"\n", ConsoleViewContentType.ERROR_OUTPUT);
- consoleView.performWhenNoDeferredOutput(
- new Runnable() {
- public void run() {
- consoleView.scrollTo(0);
- }
- }
- );
+ if (consoleView instanceof ConsoleViewImpl) {
+ ((ConsoleViewImpl)consoleView).foldImmediately();
+ }
+ consoleView.scrollTo(0);
}
@Nullable
@NonNls
public String toString() {
return "LogicalPosition: line=" + line + " column=" + column + "; visual position aware=" + visualPositionAware
- + " soft wrap: lines=" + (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine) + " (before=" +
+ + "; soft wrap: lines=" + (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine) + " (before=" +
softWrapLinesBeforeCurrentLogicalLine + "; current=" + softWrapLinesOnCurrentLogicalLine
+ ") columns diff=" + softWrapColumnDiff + "; folding: lines = " + foldedLines + " columns diff=" + foldingColumnDiff;
}
import com.intellij.CommonBundle;
import com.intellij.ui.components.JBList;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
* @author anna
* @since 5.1
*/
-public abstract class AddDeleteListPanel extends PanelWithButtons {
+public abstract class AddDeleteListPanel<T> extends PanelWithButtons {
private final String myTitle;
protected JButton myAddButton = new JButton(CommonBundle.message("button.add"));
protected JButton myDeleteButton = new JButton(CommonBundle.message("button.delete"));
protected JList myList = new JBList(myListModel);
public AddDeleteListPanel(final String title,
- final List initialList) {
+ final List<T> initialList) {
myTitle = title;
for (Object o : initialList) {
if (o != null) {
});
myAddButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
- final Object itemToAdd = findItemToAdd();
- if (itemToAdd != null){
- myListModel.addElement(itemToAdd);
- myList.setSelectedValue(itemToAdd, true);
- }
+ addElement(findItemToAdd());
}
});
myDeleteButton.addActionListener(new ActionListener() {
initPanel();
}
- protected abstract Object findItemToAdd();
+ protected void addElement(@Nullable T itemToAdd) {
+ if (itemToAdd != null){
+ myListModel.addElement(itemToAdd);
+ myList.setSelectedValue(itemToAdd, true);
+ }
+ }
+
+ @Nullable
+ protected abstract T findItemToAdd();
public Object [] getListItems(){
List<Object> items = new ArrayList<Object>();
--- /dev/null
+package com.intellij.ui;
+
+import com.intellij.CommonBundle;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.List;
+
+/**
+ * @author peter
+ */
+public abstract class AddEditDeleteListPanel<T> extends AddDeleteListPanel<T> {
+ private JButton myEditButton;
+
+ public AddEditDeleteListPanel(final String title, final List<T> initialList) {
+ super(title, initialList);
+ myEditButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ editSelectedItem();
+ }
+ });
+ myList.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
+ editSelectedItem();
+ }
+ }
+ });
+ }
+
+ @Override protected JButton[] createButtons() {
+ myEditButton = new JButton(CommonBundle.message("button.edit"));
+ return new JButton[] { myAddButton, myEditButton, myDeleteButton };
+ }
+
+ @Nullable
+ protected abstract T editSelectedItem(T item);
+
+ private void editSelectedItem() {
+ int index = myList.getSelectedIndex();
+ if (index >= 0) {
+ T newValue = editSelectedItem((T) myListModel.get(index));
+ if (newValue != null) {
+ myListModel.set(index, newValue);
+ }
+ }
+ }
+
+
+}
virtualFile.isDirectory() && virtualFile.findChild(DIRECTORY_BASED_PROJECT_DIR) != null) {
return openProject(path, projectToClose, forceOpenInNewFrame);
}
+ if (virtualFile.isDirectory()) {
+ for (VirtualFile child : virtualFile.getChildren()) {
+ final String childPath = child.getPath();
+ if (childPath.endsWith(ProjectFileType.DOT_DEFAULT_EXTENSION)) {
+ return openProject(childPath, projectToClose, forceOpenInNewFrame);
+ }
+ }
+ }
ProjectOpenProcessor provider = ProjectOpenProcessor.getImportProvider(virtualFile);
if (provider != null) {
return provider.doOpenProject(virtualFile, projectToClose, forceOpenInNewFrame);
*/
package com.intellij.openapi.editor.ex;
+import com.intellij.openapi.editor.TextChange;
+import org.jetbrains.annotations.NotNull;
+
/**
* Defines a contract for the callbacks for soft wraps management notifications (addition/removal).
*
public interface SoftWrapChangeListener {
/**
- * This method is assumed to be called every time number of soft wraps registered for the target logical line(s)
- * is changed (soft wraps are added or remove).
+ * This method is assumed to be called every new soft wrap is registered.
*
- * @param changedLogicalLine logical line for which number of registered soft wraps is changed
+ * @param softWrap newly registered soft wrap
*/
- void softWrapsStateChanged(int changedLogicalLine);
+ void softWrapAdded(@NotNull TextChange softWrap);
}
List<? extends TextChange> softWraps = editor.getSoftWrapModel().getSoftWrapsForLine(resultLogLine);
for (int i = 0; i < softWraps.size(); i++) {
TextChange softWrap = softWraps.get(i);
+ CharSequence text = document.getCharsSequence();
+ if (visualLinesToSkip <= 0) {
+ int result = editor.offsetToVisualPosition(softWrap.getStart() - 1).column;
+ // We need to add width of the next symbol because current result column points to the last symbol before the soft wrap.
+ return result + textWidthInColumns(editor, text, softWrap.getStart() - 1, softWrap.getStart(), result);
+ }
+
int softWrapLineFeeds = StringUtil.countNewLines(softWrap.getText());
if (softWrapLineFeeds < visualLinesToSkip) {
visualLinesToSkip -= softWrapLineFeeds;
continue;
}
- // Target visual column is the one just before line feed introduced by the next line feed.
+ // Target visual column is located on the last visual line of the current soft wrap.
if (softWrapLineFeeds == visualLinesToSkip) {
if (i >= softWraps.size() - 1) {
return resVisEnd.column;
TextChange nextSoftWrap = softWraps.get(i + 1);
int result = editor.offsetToVisualPosition(nextSoftWrap.getStart() - 1).column;
- // We need to add '1' because current column points to the last symbol before the next soft wrap;
- result++;
+ // We need to add symbol width because current column points to the last symbol before the next soft wrap;
+ result += textWidthInColumns(editor, text, nextSoftWrap.getStart() - 1, nextSoftWrap.getStart(), result);
int lineFeedIndex = StringUtil.indexOf(nextSoftWrap.getText(), '\n');
- result += calcColumnNumber(editor, nextSoftWrap.getText(), 0, lineFeedIndex);
+ result += textWidthInColumns(editor, nextSoftWrap.getText(), 0, lineFeedIndex, result);
return result;
}
}
}
int result = editor.offsetToVisualPosition(softWrap.getStart() - 1).column; // Column of the symbol just before the soft wrap
- result++; // Because we calculated column of the symbol just before the soft wrap
+ // Target visual column is located on the last visual line of the current soft wrap.
+ result += textWidthInColumns(editor, text, softWrap.getStart() - 1, softWrap.getStart(), result);
result += calcColumnNumber(editor, softWrap.getText(), softWrapStartOffset, softWrapEndOffset);
return result;
}
return (nTabs + 1) * tabSize;
}
+ /**
+ * Allows to answer how many columns are used to represent tabulation symbols that is started at the given visual column
+ * at the given editor.
+ *
+ * @param visualColumn visual column where target tabulation symbol starts
+ * @param editor target editor where tabulation symbol is to be represented
+ * @return number of visual columns required to represent tabulation symbols that starts at the given column
+ */
+ public static int tabWidthInColumns(@NotNull Editor editor, int visualColumn) {
+ if (!editor.getSettings().isWhitespacesShown()) {
+ return 1;
+ }
+ int tabSize = getTabSize(editor);
+ int tabsNumber = visualColumn / tabSize;
+ return (tabsNumber + 1) * tabSize - visualColumn;
+ }
+
+ public static int textWidthInColumns(@NotNull Editor editor, CharSequence text, int start, int end, int columnOffset) {
+ int result = 0;
+ for (int i = start; i < end; i++) {
+ if (text.charAt(i) == '\t') {
+ result += tabWidthInColumns(editor, columnOffset + result);
+ }
+ else {
+ result++;
+ }
+ }
+ return result;
+ }
+
/**
* Allows to answer what width in pixels is required to draw fragment of the given char array from <code>[start; end)</code> interval
* at the given editor.
* @param start offset within the given char array that points to target text start (inclusive)
* @param end offset within the given char array that points to target text end (exclusive)
* @param fontType font type to use for target text representation
+ * @param x <code>'x'</code> coordinate that should be used as a starting point for target text representation.
+ * It's necessity is implied by the fact that IDEA editor may represent tabulation symbols in any range
+ * from <code>[1; tab size]</code> (check {@link #nextTabStop(int, Editor)} for more details)
* @return width in pixels required for target text representation
*/
- public static int textWidth(@NotNull Editor editor, char[] text, int start, int end, int fontType) {
+ public static int textWidth(@NotNull Editor editor, char[] text, int start, int end, int fontType, int x) {
int result = 0;
for (int i = start; i < end; i++) {
char c = text[i];
}
if (editor.getSettings().isWhitespacesShown()) {
- result += getTabSize(editor) * getSpaceWidth(fontType, editor);
+ result += nextTabStop(x + result, editor) - result - x;
}
else {
result += getSpaceWidth(fontType, editor);
mySoftWrapModel.addSoftWrapChangeListener(new SoftWrapChangeListener() {
@Override
- public void softWrapsStateChanged(int changedLogicalLine) {
+ public void softWrapAdded(@NotNull TextChange softWrap) {
mySoftWrapsChanged = true;
- mySizeContainer.update(changedLogicalLine, changedLogicalLine, changedLogicalLine);
+ int softWrapLine = myDocument.getLineNumber(softWrap.getStart());
+ mySizeContainer.update(softWrapLine, softWrapLine, softWrapLine);
}
});
if (i >= 0) {
start = i + 1;
}
- return new Point(EditorUtil.textWidth(this, softWrapChars, start, column + 1, Font.PLAIN), y);
+ return new Point(EditorUtil.textWidth(this, softWrapChars, start, column + 1, Font.PLAIN, 0), y);
}
break;
}
myGutterComponent.repaint(0, clip.y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - clip.y);
// Ask caret model to update visual caret position.
- getCaretModel().moveToOffset(getCaretModel().getOffset());
+ //TODO den implement
+ //getCaretModel().moveToOffset(getCaretModel().getOffset());
}
}
private int myMaxWidth = -1;
public synchronized void reset() {
- int visLinesCount = getDocument().getLineCount();
- myLineWidths = new TIntArrayList(visLinesCount + 300);
- int[] values = new int[visLinesCount];
+ int lineCount = getDocument().getLineCount();
+ myLineWidths = new TIntArrayList(lineCount + 300);
+ int[] values = new int[lineCount];
Arrays.fill(values, -1);
myLineWidths.add(values);
myIsDirty = true;
*/
public class SoftWrapModelImpl implements SoftWrapModelEx {
- private final SoftWrapDataMapper myDataAdjuster;
+ private final SoftWrapDataMapper myDataAdjuster;
private final SoftWrapsStorage myStorage;
private final SoftWrapPainter myPainter;
private final SoftWrapApplianceManager myApplianceManager;
private int myActive;
public SoftWrapModelImpl(@NotNull EditorEx editor) {
- this(editor, new SoftWrapsStorage(editor.getDocument()), new CompositeSoftWrapPainter(editor));
+ this(editor, new SoftWrapsStorage(), new CompositeSoftWrapPainter(editor));
}
public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter) {
}
if (start < end) {
- result += EditorUtil.textWidth(myEditor, chars, start, end, Font.PLAIN);
+ result += EditorUtil.textWidth(myEditor, chars, start, end, Font.PLAIN, 0);
}
return result;
int x = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
int prevSoftWrapOffset = start;
for (int i = start; i < end; i++) {
- int symbolWidth = EditorUtil.textWidth(myEditor, text, i, i + 1, fontType);
+ int symbolWidth = EditorUtil.textWidth(myEditor, text, i, i + 1, fontType, x);
if (x + symbolWidth >= myVisibleAreaWidth) {
int offset = calculateSoftWrapOffset(text, i - 1, prevSoftWrapOffset, end);
if (offset >= end || offset <= prevSoftWrapOffset) {
// Return eagerly if there are no soft wraps before the target offset on a line that contains it.
if (max >= softWraps.size() || softWraps.get(max).getStart() > offset) {
- int column = toVisualColumnSymbolsNumber(chars, targetLineStartOffset, offset);
+ int column = toVisualColumnSymbolsNumber(chars, targetLineStartOffset, offset, 0);
LogicalPosition foldingUnawarePosition = new LogicalPosition(
rawLineStartLogicalPosition.line, column, softWrapIntroducedLinesBefore, 0, 0, 0, 0
);
}
// Assuming that no line feed is contained before target offset on a line that holds it.
- symbolsOnCurrentLogicalLine++;
- symbolsOnCurrentVisibleLine++;
+ int columnsForSymbol = toVisualColumnSymbolsNumber(chars.charAt(i), symbolsOnCurrentVisibleLine);
+ symbolsOnCurrentLogicalLine += columnsForSymbol;
+ symbolsOnCurrentVisibleLine += columnsForSymbol;
}
LogicalPosition foldingUnawarePosition = new LogicalPosition(
int foldColumnDiff = 0;
int softWrapColumnDiff = position.softWrapColumnDiff;
Document document = myEditor.getDocument();
- CharSequence text = document.getCharsSequence();
int targetLine = document.getLineNumber(offset);
+ int lastFoldEndLogicalLine = -1;
for (FoldRegion foldRegion : foldingModel.getAllFoldRegions()) {
if (foldRegion.getStartOffset() >= offset) {
break;
foldedLines += Math.min(targetLine, foldingEndLine) - foldingStartLine;
// Process situation when target offset is located inside the folded region.
- if (offset >= foldRegion.getStartOffset() && offset < foldRegion.getEndOffset()) {
- // Our purpose is to define folding data in order to point to the visual folding start.
- int visualFoldingStartColumn = calculateVisualFoldingStartColumn(foldRegion);
- foldColumnDiff = visualFoldingStartColumn - position.column - softWrapColumnDiff;
- break;
- }
-
- if (foldingEndLine != position.line) {
- continue;
- }
+ if (offset >= foldRegion.getStartOffset()) {
+ if (offset < foldRegion.getEndOffset()) {
+ // Our purpose is to define folding data in order to point to the visual folding start.
+ int visualFoldingStartColumn = calculateVisualFoldingStartColumn(foldRegion);
+ int diff = visualFoldingStartColumn - position.column - softWrapColumnDiff;
+ if (lastFoldEndLogicalLine == foldingStartLine) {
+ foldColumnDiff += diff;
+ }
+ else {
+ foldColumnDiff = diff;
+ }
+ return new LogicalPosition(
+ position.line, position.column, position.softWrapLinesBeforeCurrentLogicalLine, position.softWrapLinesOnCurrentLogicalLine,
+ softWrapColumnDiff, foldedLines, foldColumnDiff
+ );
+ }
- // We know here that offset is at the same line where folding ends and is located after it. Hence, we process that as follows:
- // 1. Check if the folding is single-line;
- // 2.1. Process as follows if the folding is single-line:
- // 3.1. Calculate column difference introduced by the folding;
- // 2.2. Process as follows if the folding is multi-line:
- // 3.2. Calculate visual column of folding start;
- // 4.2. Calculate number of columns between target offset and folding end;
- // 5.1. Calculate folding placeholder width in columns;
- // 6.1. Calculate resulting offset visual column;
- // 7.1. Calculate resulting folding column diff;
-
- if (foldingStartLine == foldingEndLine) {
- foldColumnDiff = toVisualColumnSymbolsNumber(foldRegion.getPlaceholderText())
- - toVisualColumnSymbolsNumber(text, foldRegion.getStartOffset(), foldRegion.getEndOffset());
- }
- else {
- int endOffsetOfLineWithFoldingEnd = document.getLineEndOffset(foldingEndLine);
- int columnsBetweenFoldingEndAndOffset = toVisualColumnSymbolsNumber(text, foldRegion.getEndOffset(), endOffsetOfLineWithFoldingEnd);
- LogicalPosition foldingEndLineEndPosition = myEditor.offsetToLogicalPosition(endOffsetOfLineWithFoldingEnd);
- if (position.column > foldingEndLineEndPosition.column) {
- columnsBetweenFoldingEndAndOffset += position.column - foldingEndLineEndPosition.column;
+ int diff = getFoldColumnDiff(foldRegion);
+ if (lastFoldEndLogicalLine == foldingStartLine) {
+ foldColumnDiff += diff;
}
- int visualFoldingStartColumn = calculateVisualFoldingStartColumn(foldRegion);
- int foldingPlaceholderWidth = toVisualColumnSymbolsNumber(foldRegion.getPlaceholderText());
- int visual = columnsBetweenFoldingEndAndOffset + visualFoldingStartColumn + foldingPlaceholderWidth;
- foldColumnDiff = visual - position.column;
- break;
+ else {
+ foldColumnDiff = diff;
+ }
+ lastFoldEndLogicalLine = foldingEndLine;
}
}
+ if (lastFoldEndLogicalLine != position.line) {
+ foldColumnDiff = 0;
+ }
+
return new LogicalPosition(
position.line, position.column, position.softWrapLinesBeforeCurrentLogicalLine, position.softWrapLinesOnCurrentLogicalLine,
softWrapColumnDiff, foldedLines, foldColumnDiff
);
}
+ private int getFoldColumnDiff(FoldRegion region) {
+ int visualFoldingStartColumn = calculateVisualFoldingStartColumn(region);
+ LogicalPosition foldEndLogical = myEditor.offsetToLogicalPosition(region.getEndOffset());
+ // Assuming that there is no tabulations symbols at placeholder text.
+ int foldingPlaceholderWidth = region.getPlaceholderText().length();
+ return visualFoldingStartColumn + foldingPlaceholderWidth - foldEndLogical.column;
+ }
+
private int calculateVisualFoldingStartColumn(FoldRegion region) {
Document document = myEditor.getDocument();
int foldingStartOffset = region.getStartOffset();
List<TextChangeImpl> softWraps = myStorage.getSoftWraps();
int startOffsetOfVisualLineWithFoldingStart = logicalLineStartOffset;
+ int softWrapOffsetInColumns = 0;
for (; softWrapIndex < softWraps.size(); softWrapIndex++) {
TextChange softWrap = softWraps.get(softWrapIndex);
if (softWrap.getStart() >= foldingStartOffset) {
}
startOffsetOfVisualLineWithFoldingStart = softWrap.getStart();
+ softWrapOffsetInColumns = numberOfSymbolsOnLastVisualLine(softWrap);
}
assert startOffsetOfVisualLineWithFoldingStart <= foldingStartOffset;
- return toVisualColumnSymbolsNumber(document.getCharsSequence(), startOffsetOfVisualLineWithFoldingStart, foldingStartOffset);
+ return EditorUtil.textWidthInColumns(
+ myEditor, document.getCharsSequence(), startOffsetOfVisualLineWithFoldingStart, foldingStartOffset, softWrapOffsetInColumns
+ );
}
- private int toVisualColumnSymbolsNumber(char c) {
+ private static int numberOfSymbolsOnLastVisualLine(TextChange textChange) {
+ int result = 0;
+ for (int i = textChange.getText().length() - 1; i >= 0; i--) {
+ if (i == '\n') {
+ return result;
+ }
+ else {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ private int toVisualColumnSymbolsNumber(char c, int offsetInColumns) {
myCharBuffer.clear();
myCharBuffer.put(c);
myCharBuffer.flip();
- return toVisualColumnSymbolsNumber(myCharBuffer, 0, 1);
- }
-
- private int toVisualColumnSymbolsNumber(CharSequence text) {
- return toVisualColumnSymbolsNumber(text, 0, text.length());
+ return toVisualColumnSymbolsNumber(myCharBuffer, 0, 1, offsetInColumns);
}
- private int toVisualColumnSymbolsNumber(CharSequence text, int start, int end) {
- return EditorUtil.calcColumnNumber(myEditor, text, start, end);
+ private int toVisualColumnSymbolsNumber(CharSequence text, int start, int end, int offsetInColumns) {
+ int result = 0;
+ for (int i = start; i < end; i++) {
+ if (text.charAt(i) == '\t') {
+ result += EditorUtil.tabWidthInColumns(myEditor, offsetInColumns + result);
+ }
+ else {
+ result++;
+ }
+ }
+ return result;
}
private class Context {
public int targetSoftWrapLines;
public int symbolsOnCurrentLogicalLine;
public int symbolsOnCurrentVisualLine;
+ /**
+ * There is a possible case that single tabulation symbols is shown in more than one visual column (IntelliJ editor is configured
+ * to show white spaces and tabulations and tab size is more than one). We keep track in number of such excessive visual
+ * columns used to show tabulations on a current visual line.
+ */
+ public int excessiveTabColumns;
Context(LogicalPosition softWrapUnawareLogicalPosition, VisualPosition targetVisualPosition, int softWrapLinesBefore,
int softWrapLinesOnCurrentLineBeforeTargetSoftWrap, int visualLineBeforeSoftWrapAppliance, FoldingModel foldingModel)
else {
targetSoftWrapLines++;
symbolsOnCurrentVisualLine = 0;
+ excessiveTabColumns = 0;
return null;
}
}
// Just update information about tracked symbols number if current visual line is too low.
if (targetVisualPosition.line > visualLineBeforeSoftWrapAppliance + targetSoftWrapLines) {
- symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
+ symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c, symbolsOnCurrentVisualLine);
return null;
}
}
// Process non-line feed inside soft wrap.
- symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
+ symbolsOnCurrentVisualLine++; // Don't expect tabulation to be used inside soft wrap text.
if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
return build();
}
// Just update information about tracked symbols number if current visual line is too low.
if (targetVisualPosition.line > visualLineBeforeSoftWrapAppliance + targetSoftWrapLines) {
- symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
- symbolsOnCurrentLogicalLine++;
+ int columnsForSymbol = toVisualColumnSymbolsNumber(c, symbolsOnCurrentVisualLine);
+ symbolsOnCurrentVisualLine += columnsForSymbol;
+ symbolsOnCurrentLogicalLine += columnsForSymbol;
return null;
}
return build();
}
- symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
- symbolsOnCurrentLogicalLine++;
-
+ int columnsForSymbol = toVisualColumnSymbolsNumber(c, symbolsOnCurrentVisualLine);
+ int diffInColumns = targetVisualPosition.column - symbolsOnCurrentVisualLine;
+ int incrementToUse = columnsForSymbol;
+ if (columnsForSymbol >= diffInColumns) {
+ incrementToUse = Math.min(columnsForSymbol, diffInColumns);
+ }
+ symbolsOnCurrentVisualLine += incrementToUse;
+ symbolsOnCurrentLogicalLine += incrementToUse;
if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
return build();
*/
package com.intellij.openapi.editor.impl.softwrap;
-import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.SoftWrapChangeListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
private final List<TextChangeImpl> myWrapsView = Collections.unmodifiableList(myWraps);
private final Set<SoftWrapChangeListener> myListeners = new CopyOnWriteArraySet<SoftWrapChangeListener>();
- private final Document myDocument;
-
- public SoftWrapsStorage(Document document) {
- myDocument = document;
- }
-
/**
* @return <code>true</code> if there is at least one soft wrap registered at the current storage; <code>false</code> otherwise
*/
i = -i - 1;
myWraps.add(i, softWrap);
- int changedLogicalLine = myDocument.getLineNumber(softWrap.getStart());
for (SoftWrapChangeListener listener : myListeners) {
- listener.softWrapsStateChanged(changedLogicalLine);
+ listener.softWrapAdded(softWrap);
}
return null;
}
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.CustomStatusBarWidget;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.StatusBarCustomComponentFactory;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
void setMemoryIndicatorVisible(final boolean visible) {
if (myMemoryWidget != null) {
myMemoryWidget.setShowing(visible);
+ if (!SystemInfo.isMac) {
+ myStatusBar.setBorder(BorderFactory.createEmptyBorder(1, 4, 0, visible ? 0 : 2));
+ }
}
}
public IdeStatusBarImpl() {
setLayout(new BorderLayout());
- setBorder(BorderFactory.createEmptyBorder(1, 4, 0, 2));
+ setBorder(BorderFactory.createEmptyBorder(1, 4, 0, SystemInfo.isMac ? 2 : 0));
myInfoAndProgressPanel = new InfoAndProgressPanel();
addWidget(myInfoAndProgressPanel, Position.CENTER);
final long maxMemory = runtime.maxMemory();
final long freeMemory = maxMemory - runtime.totalMemory() + runtime.freeMemory();
- final Insets insets = getInsets();
+ final Insets insets = SystemInfo.isMac ? getInsets() : new Insets(0, 0, 0, 0);
final int totalBarLength = size.width - insets.left - insets.right - (SystemInfo.isMac ? 0 : 0);
final int usedBarLength = totalBarLength - (int)(totalBarLength * freeMemory / maxMemory);
- final int barHeight = HEIGHT; // size.height - insets.top - insets.bottom;
+ final int barHeight = SystemInfo.isMac ? HEIGHT : size.height - insets.top - insets.bottom;
final Graphics2D g2 = (Graphics2D)g;
final int yOffset = (size.height - barHeight) / 2;
g2.setPaint(new GradientPaint(1, 1, new Color(175, 185, 202), 0, size.height - 2, new Color(126, 138, 168)));
g2.fillRect(xOffset + 1, yOffset, usedBarLength, barHeight);
- g2.setColor(new Color(194, 197, 203));
- g2.drawLine(xOffset + 1, yOffset+1, xOffset + usedBarLength, yOffset+1);
+ if (SystemInfo.isMac) {
+ g2.setColor(new Color(194, 197, 203));
+ g2.drawLine(xOffset + 1, yOffset+1, xOffset + usedBarLength, yOffset+1);
+ }
}
- g2.setColor(new Color(110, 110, 110));
- g2.drawRect(xOffset, yOffset, totalBarLength, barHeight - 1);
+ if (SystemInfo.isMac) {
+ g2.setColor(new Color(110, 110, 110));
+ g2.drawRect(xOffset, yOffset, totalBarLength, barHeight - 1);
+ }
g.setFont(getFont());
final long used = (maxMemory - freeMemory) / MEGABYTE;
public final int getPreferredWidth() {
final Insets insets = getInsets();
- return getFontMetrics(UIUtil.getLabelFont().deriveFont(11.0f)).stringWidth(SAMPLE_STRING) + insets.left + insets.right + (SystemInfo.isMac ? 2 : 0);
+ return getFontMetrics(SystemInfo.isMac ? UIUtil.getLabelFont().deriveFont(11.0f) : UIUtil.getLabelFont()).stringWidth(SAMPLE_STRING) + insets.left + insets.right + (SystemInfo.isMac ? 2 : 0);
}
@Override
package com.intellij.openapi.editor.impl.softwrap;
-import com.intellij.idea.Bombed;
import com.intellij.mock.MockFoldRegion;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorEx;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.Nullable;
import org.jmock.Expectations;
+import org.jmock.Mockery;
import org.jmock.api.Invocation;
-import org.jmock.lib.action.CustomAction;
-import org.junit.Test;
-import org.junit.Before;
-import org.junit.After;
import org.jmock.integration.junit4.JUnit4Mockery;
-import org.jmock.Mockery;
+import org.jmock.lib.action.CustomAction;
import org.jmock.lib.legacy.ClassImposteriser;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
/**
* @author Denis Zhdanov
// There is a possible case that multiple logical positions match to the same visual position (e.g. logical
// positions for folded text match to the same visual position). We want to match to the logical position of
// folding region start if we search by logical position from folded text.
- if (o1.foldedSpace & o2.foldedSpace && logical1.column + logical1.foldingColumnDiff == logical2.foldingColumnDiff) {
+ if (o1.foldedSpace && o2.foldedSpace && logical1.column + logical1.foldingColumnDiff == logical2.foldingColumnDiff) {
return o1.foldedSpace ? 1 : -1;
}
return logical1.column - logical2.column;
private static final Comparator<DataEntry> OFFSETS_COMPARATOR = new Comparator<DataEntry>() {
@Override
public int compare(DataEntry o1, DataEntry o2) {
+ if (o1.offset != o2.offset) {
+ return o1.offset - o2.offset;
+ }
// There are numerous situations when multiple visual positions share the same offset (e.g. all soft wrap-introduced virtual
// spaces share offset with the first document symbol after soft wrap or all virtual spaces after line end share the same offset
// as the last line symbol). We want to ignore such positions during lookup by offset.
- if (o1.offset == o2.offset && o1.virtualSpace ^ o2.virtualSpace) {
+ if (o1.virtualSpace ^ o2.virtualSpace) {
return o1.virtualSpace ? 1 : -1;
}
- return o1.offset - o2.offset;
+ if (o1.insideTab ^ o2.insideTab) {
+ return o1.insideTab ? 1 : -1;
+ }
+ return 0;
}
};
myEditor = myMockery.mock(EditorEx.class);
myDocument = myMockery.mock(Document.class);
- myStorage = new SoftWrapsStorage(myDocument);
+ myStorage = new SoftWrapsStorage();
myFoldingModel = myMockery.mock(FoldingModel.class);
final EditorSettings settings = myMockery.mock(EditorSettings.class);
final Project project = myMockery.mock(Project.class);
allowing(myEditor).getSettings();will(returnValue(settings));
allowing(settings).isUseSoftWraps();will(returnValue(true));
allowing(settings).getTabSize(project);will(returnValue(TAB_SIZE));
+ allowing(settings).isWhitespacesShown();will(returnValue(true));
allowing(myEditor).getProject();will(returnValue(project));
// Folding.
myMockery.assertIsSatisfied();
}
- @Bombed(day = 12, month = Calendar.JULY)
@Test
public void softWrapHasSymbolBeforeFirstLineFeed() {
String document =
test(document);
}
- @Bombed(day = 12, month = Calendar.JULY)
@Test
public void multipleSoftWrappedLogicalLines() {
String document =
test(document);
}
- @Bombed(day = 12, month = Calendar.JULY)
@Test
public void softWrapAndFoldedLines() {
String document =
test(document);
}
+ @Test
+ public void tabSymbolsBeforeSoftWrap() {
+ String document =
+ "class Test\t\t{<WRAP>\n" +
+ " </WRAP> \n}";
+ test(document);
+ }
+
+ @Test
+ public void tabSymbolsAfterSoftWrap() {
+ String document =
+ "class Test {<WRAP>\n" +
+ " </WRAP> \t\t\n" +
+ "}";
+ test(document);
+ }
+
+ @Test
+ public void multipleTabsAndSoftWraps() {
+ String document =
+ "public class \tTest {\n" +
+ " public void foo(int[] data) {\n" +
+ " bar(data[0], data[1],\t\t <WRAP>\n" +
+ " </WRAP>data[2], data[3], <WRAP>\t \t\n" +
+ " </WRAP>data[4], data[5],\t \t \n" +
+ " data[6], data[7],\t \t \n" +
+ " data[8], data[9],\t \t <WRAP>\n" +
+ " </WRAP>data[10], data[11], <WRAP>\t \t \n" +
+ " </WRAP>data[12],\t \t data[13]); \n" +
+ " }\n" +
+ " public void bar(int ... i) {\n" +
+ " }\n" +
+ "}";
+ test(document);
+ }
+
+ @Test
+ public void tabBeforeFolding() {
+ String document =
+ "class Test\t \t <FOLD>{\n" +
+ " </FOLD> \t\t\n" +
+ "}";
+ test(document);
+ }
+
+ @Test
+ public void multipleTabsAndFolding() {
+ String document =
+ "public class \tTest {\n" +
+ " public void foo(int[] data) {\n" +
+ " bar(data[0], data[1],\t\t <FOLD>\n" +
+ " \t \t </FOLD>data[2], data[3], <FOLD>\t \t\n" +
+ " \t \t </FOLD>data[4], data[5],\t \t \n" +
+ " data[6], data[7],\t \t \n" +
+ " data[8], data[9],\t \t <FOLD>\n" +
+ "\t \t </FOLD>data[10], data[11], <FOLD>\t \t \n" +
+ " \t \t </FOLD>data[12],\t \t data[13]); \n" +
+ " }\n" +
+ " public void bar(int ... i) {\n" +
+ " }\n" +
+ "}";
+ test(document);
+ }
+
private int getLineNumber(int offset) {
int line = 0;
for (TextRange range : myLineRanges) {
LogicalPosition actualLogicalByVisual = myAdjuster.adjustLogicalPosition(toSoftWrapUnawareLogicalByVisual(data), data.visual);
// We don't want to perform the check for logical positions that correspond to the folded space because all of them relate to
// the same logical position of the folding start.
- if (!data.foldedSpace && !equals(data.logical, actualLogicalByVisual)) {
+ if (!data.foldedSpace && !data.insideTab && !equals(data.logical, actualLogicalByVisual)) {
throw new AssertionError(
String.format("Detected unmatched logical position by visual (%s). Expected: '%s', actual: '%s'. Calculation was performed "
+ "against soft wrap-unaware logical: '%s'",
LogicalPosition actualLogicalByOffset = myAdjuster.offsetToLogicalPosition(data.offset);
// We don't to perform the check for the data that points to soft wrap location here. The reason is that it shares offset
// with the first document symbol after soft wrap, hence, examination always fails.
- if (!data.virtualSpace && !equals(data.logical, actualLogicalByOffset)) {
+ if (!data.virtualSpace && !data.insideTab && !equals(data.logical, actualLogicalByOffset)) {
throw new AssertionError(
String.format("Detected unmatched logical position by offset. Expected: '%s', actual: '%s'. Calculation was performed "
+ "against offset: '%d' and soft wrap-unaware logical: '%s'",
public final int offset;
public final boolean foldedSpace;
public final boolean virtualSpace;
+ public final boolean insideTab;
DataEntry(VisualPosition visual, LogicalPosition logical, int offset, boolean foldedSpace) {
- this(visual, logical, offset, foldedSpace, false);
+ this(visual, logical, offset, foldedSpace, false, false);
}
- DataEntry(VisualPosition visual, LogicalPosition logical, int offset, boolean foldedSpace, boolean virtualSpace) {
+ DataEntry(VisualPosition visual, LogicalPosition logical, int offset, boolean foldedSpace, boolean virtualSpace, boolean insideTab) {
this.visual = visual;
this.logical = logical;
this.offset = offset;
this.foldedSpace = foldedSpace;
this.virtualSpace = virtualSpace;
+ this.insideTab = insideTab;
}
@Override
boolean insideSoftWrap;
boolean insideFolding;
+ boolean insideTab;
int logicalLineStartOffset;
int logicalLine;
int logicalColumn;
int foldingColumnDiff;
int foldedLines;
int offset;
+ int tabAnchorColumn;
public void onSoftWrapStart() {
softWrapStartOffset = offset;
public void onSoftWrapEnd() {
myStorage.storeOrReplace(new TextChangeImpl(mySoftWrapBuffer.toString(), softWrapStartOffset));
mySoftWrapBuffer.setLength(0);
- visualColumn++; // For the column reserved for soft wrap sign.
insideSoftWrap = false;
}
onNonSoftWrapSymbol(c);
if (c == '\n') {
foldedLines++;
+ offset++;
+ tabAnchorColumn = 0;
+ }
+ else if (c == '\t') {
+ int tabsNumber = tabAnchorColumn / TAB_SIZE;
+ int tabWidthInColumns = ((tabsNumber + 1) * TAB_SIZE) - tabAnchorColumn;
+
+ // There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
+ // We store data entry only for the first tab column without 'inside tab' flag then.
+ insideTab = true;
+ for (int i =tabWidthInColumns - 1; i > 0; i--) {
+ logicalColumn++;
+ addData(false);
+ }
+ insideTab = false;
+
+ logicalColumn++;
+ offset++;
+ tabAnchorColumn += tabWidthInColumns;
+ } else {
+ logicalColumn++;
+ offset++;
+ tabAnchorColumn++;
}
foldingColumnDiff = foldingStartVisualColumn - logicalColumn;
return;
visualLine++;
softWrapLinesOnCurrentLogical++;
- visualColumn = 0;
+ visualColumn = 1; // For the column reserved for soft wrap sign.
+ tabAnchorColumn = 1;
softWrapSymbolsOnCurrentVisualLine = 0;
}
else {
visualColumn++;
softWrapSymbolsOnCurrentVisualLine++;
+ tabAnchorColumn++;
}
return;
}
if (c == '\n') {
visualLine++;
visualColumn = 0;
+ tabAnchorColumn = 0;
softWrapLinesBeforeCurrentLogical += softWrapLinesOnCurrentLogical;
softWrapLinesOnCurrentLogical = 0;
softWrapSymbolsOnCurrentVisualLine = 0;
foldingColumnDiff = 0;
+ offset++;
+ }
+ else if (c == '\t') {
+ int tabsNumber = tabAnchorColumn / TAB_SIZE;
+ int tabWidthInColumns = ((tabsNumber + 1) * TAB_SIZE) - tabAnchorColumn;
+
+ // There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
+ // We store data entry only for the first tab column without 'inside tab' flag then.
+ insideTab = true;
+ for (int i = tabWidthInColumns - 1; i > 0; i--) {
+ visualColumn++;
+ logicalColumn++;
+ addData(false);
+ }
+ insideTab = false;
+
+ visualColumn++;
+ logicalColumn++;
+ offset++;
+ tabAnchorColumn += tabWidthInColumns;
}
else {
visualColumn++;
+ logicalColumn++;
+ offset++;
+ tabAnchorColumn++;
}
}
logicalLine++;
logicalColumn = 0;
}
- else {
- logicalColumn++;
- }
- offset++;
}
private void addData() {
private void addData(boolean virtualSpace) {
myExpectedData.add(new DataEntry(
- buildVisualPosition(), buildLogicalPosition(), offset, insideFolding && offset != foldingStartOffset, virtualSpace
+ buildVisualPosition(), buildLogicalPosition(), offset, insideFolding && offset != foldingStartOffset, virtualSpace, insideTab
));
}
declaration.s.to.be.generified=Declaration(s) to be generified {0}
occurences.to.be.migrated=Occurrences to be migrated {0}
references.in.code=References in code {0}
-safe.delete.comment.occurences.header=Occurrences found in comments, strings and non-java files {0}. Those occurrences will not be changed
+safe.delete.comment.occurences.header=Occurrences found in comments, strings and non-code files {0}. Those occurrences will not be changed
move.single.element.elements.header={0} to be moved to {1}
references.in.code.to.0.1=References in code to {0} {1}
move.classes.elements.header=Classes to be moved to {0}
move.packages.elements.header=Packages to be moved to {0}
references.found.in.code=References found in code
-comments.elements.header=Occurrences found in comments, strings and non-java files {0}
+comments.elements.header=Occurrences found in comments, strings and non-code files {0}
move.files.elements.header=Files to be moved to {0}
move.directories.elements.header=Directories to be moved to {0}
make.static.description.label=Make {0} {1} static
replace.default.constructor.of.0.with.a.factory.method=Replace default constructor of {0} with a factory method
replace.constructor.with.factory.method=Replace constructor with factory method
replace.default.constructor.with.factory.method=Replace default constructor with factory method
-occurrences.found.in.comments.strings.and.non.java.files=Occurrences found in comments, strings and non-java files
+occurrences.found.in.comments.strings.and.non.java.files=Occurrences found in comments, strings and non-code files
0.referenced.in.1.will.not.be.accessible.in.module.2={0}, referenced in {1}, will not be accessible in module {2}
0.referenced.in.1.will.not.be.accessible.from.module.2={0}, referenced in {1}, will not be accessible from module {2}
0.referenced.in.1.will.not.be.accessible.from.production.of.module.2={0}, referenced in {1}, will not be accessible from the production sources of module {2}
getter.and.setter.methods.found.for.the.field.0=Getter and setter methods found for the field {0}. \n{1} them as well?
getter.method.found.for.the.field.0=Getter method found for the field {0}. \n{1} the getter as well?
setter.method.found.for.the.field.0=Setter method found for the field {0}. \n{1} the setter as well?
-0.has.1.usages.in.comments.and.strings={0} has {1,choice,1#1 usage|2#{1,number} usages} in strings, comments, or non-Java files.
-0.has.1.usages.that.are.not.safe.to.delete.of.those.2={0} has {1,choice,1#1 usage that is|2#{1,number} usages that are} not safe to delete.\nOf those {2,choice,0#0 usages are|1#1 usage is|2#{2,number} usages are} in strings, comments, or non-Java files.
+0.has.1.usages.in.comments.and.strings={0} has {1,choice,1#1 usage|2#{1,number} usages} in strings, comments, or non-code files.
+0.has.1.usages.that.are.not.safe.to.delete.of.those.2={0} has {1,choice,1#1 usage that is|2#{1,number} usages that are} not safe to delete.\nOf those {2,choice,0#0 usages are|1#1 usage is|2#{2,number} usages are} in strings, comments, or non-code files.
type.cook.drop.obsolete.casts=&Drop obsolete casts
type.cook.preserve.raw.arrays=Preserve raw &arrays
type.cook.leave.object.parameterized.types.raw=&Leave Object-parameterized types raw
<extensionPoint name="typeIcon" beanClass="com.intellij.ide.TypeIconEP"/>
<extensionPoint name="analyzeStacktraceFilter" interface="com.intellij.execution.filters.Filter" area="IDEA_PROJECT"/>
+
+ <extensionPoint name="stacktrace.fold" beanClass="com.intellij.execution.console.CustomizableConsoleFoldingBean"/>
+
</extensionPoints>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.LegacyCompletionContributor" id="legacy" order="last"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.FilePathCompletionContributor" id="filePath" order="before javaClassName"/>
+ <applicationService serviceInterface="com.intellij.execution.console.ConsoleFoldingSettings" serviceImplementation="com.intellij.execution.console.ConsoleFoldingSettings"/>
+ <console.folding implementation="com.intellij.execution.console.SubstringConsoleFolding"/>
+ <applicationConfigurable implementation="com.intellij.execution.console.ConsoleFoldingConfigurable"/>
+
+ <stacktrace.fold substring="at java.lang.reflect.Method.invoke("/>
+ <stacktrace.fold substring="at java.lang.reflect.Constructor.newInstance("/>
+ <stacktrace.fold substring="at sun.reflect."/>
+
<psi.referenceContributor implementation="com.intellij.psi.PsiReferenceContributorImpl"/>
<lookup.charFilter implementation="com.intellij.codeInsight.completion.CompletionCharFilter" order="last" id="completion"/>
package com.intellij.execution.testframework.ui;
import com.intellij.execution.filters.HyperlinkInfo;
+import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.execution.testframework.*;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
}
myCurrentPrintable.printOn(this);
scrollToBeginning();
+ if (myConsole instanceof ConsoleViewImpl) {
+ ((ConsoleViewImpl)myConsole).foldImmediately();
+ }
}
public void printHyperlink(final String text, final HyperlinkInfo info) {
return hashMap;
}
- public static <K, V> HashMap<K, Set<V>> classify(Iterator<V> iterator, Convertor<V, K> keyConvertor) {
- HashMap<K, Set<V>> hashMap = new HashMap<K, Set<V>>();
+ public static <K, V> Map<K, Set<V>> classify(Iterator<V> iterator, Convertor<V, K> keyConvertor) {
+ Map<K, Set<V>> hashMap = new LinkedHashMap<K, Set<V>>();
while (iterator.hasNext()) {
V value = iterator.next();
final K key = keyConvertor.convert(value);
System.gc();
try {
List<Object> list = new ArrayList<Object>();
- while (Runtime.getRuntime().freeMemory() > 10000) {
+ while (Runtime.getRuntime().freeMemory() > 100000) {
list.add(new byte[1000]);
}
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
+import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.impl.source.tree.injected.Place;
new WriteCommandAction.Simple(myProject, origFile) {
@Override
protected void run() throws Throwable {
- commitToOriginalInner();
+ PostprocessReformattingAspect.getInstance(myProject).disablePostprocessFormattingInside(new Runnable() {
+ @Override
+ public void run() {
+ commitToOriginalInner();
+ }
+ });
}
}.execute();
}
.classify(myMarkers.entrySet().iterator(),
new Convertor<Map.Entry<SmartPsiElementPointer, Pair<RangeMarker, RangeMarker>>, PsiLanguageInjectionHost>() {
public PsiLanguageInjectionHost convert(final Map.Entry<SmartPsiElementPointer, Pair<RangeMarker, RangeMarker>> o) {
- return (PsiLanguageInjectionHost)o.getKey().getElement();
+ final PsiElement element = o.getKey().getElement();
+ return (PsiLanguageInjectionHost)element;
}
});
PsiDocumentManager.getInstance(myProject).commitDocument(myOrigDocument);
+ int localInsideFileCursor = 0;
for (PsiLanguageInjectionHost host : map.keySet()) {
+ if (host == null) continue;
final String hostText = host.getText();
TextRange insideHost = null;
final StringBuilder sb = new StringBuilder();
final TextRange localInsideHost =
new TextRange(origMarker.getStartOffset() - hostOffset, origMarker.getEndOffset() - hostOffset);
final RangeMarker rangeMarker = entry.getValue().second;
- final TextRange localInsideFile = new TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset());
+ final TextRange localInsideFile = new TextRange(Math.max(localInsideFileCursor, rangeMarker.getStartOffset()), rangeMarker.getEndOffset());
if (insideHost != null) {
+ //append unchanged inter-markers fragment
sb.append(hostText.substring(insideHost.getEndOffset(), localInsideHost.getStartOffset()));
}
- sb.append(localInsideFile.getEndOffset() <= text.length()? localInsideFile.substring(text) : "");
-
+ sb.append(localInsideFile.getEndOffset() <= text.length() && !localInsideFile.isEmpty()? localInsideFile.substring(text) : "");
+ localInsideFileCursor = localInsideFile.getEndOffset();
insideHost = insideHost == null ? localInsideHost : insideHost.union(localInsideHost);
}
assert insideHost != null;
if (StringUtil.isNotEmpty(name)) appendStringPattern(result, ".withLocalName(", name, ")");
if (StringUtil.isNotEmpty(namespace)) appendStringPattern(result, ".withNamespace(", namespace, ")");
if (StringUtil.isNotEmpty(injection.getTagName()) || StringUtil.isNotEmpty(injection.getTagNamespace())) {
- result.append(".inside(").append(XmlTagInjection.getPatternString(injection)).append(")");
+ result.append(".withParent(").append(XmlTagInjection.getPatternString(injection)).append(")");
}
return result.toString();
}
</injection>
<injection language="XPath" injector-id="xml">
<display-name>JAXB attribute node</display-name>
- <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("node")).inside(xmlTag().withLocalName(string().equalTo("bindings")).withNamespace(string().equalTo("http://java.sun.com/xml/ns/jaxb")))]]></place>
+ <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("node")).withParent(xmlTag().withLocalName(string().equalTo("bindings")).withNamespace(string().equalTo("http://java.sun.com/xml/ns/jaxb")))]]></place>
</injection>
<injection language="JavaScript" injector-id="xml">
<display-name>*/@href</display-name>
<value-pattern>^javascript:(.+)</value-pattern>
- <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("href")).inside(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
+ <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("href")).withParent(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
</injection>
<injection language="JavaScript" injector-id="xml">
<display-name>*/@on.*</display-name>
- <place><![CDATA[xmlAttribute().withLocalName(string().matches("on.*")).inside(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
+ <place><![CDATA[xmlAttribute().withLocalName(string().matches("on.*")).withParent(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
</injection>
<injection language="CSS" injector-id="xml">
<display-name>*/@style</display-name>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="module" module-name="platform-api" />
- <orderEntry type="module" module-name="lang-impl" />
- </component>
-</module>
-
+++ /dev/null
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
- <id>com.intellij.console.folding</id>
- <name>Console Folding</name>
- <description>Adds a customization for folding non-interesting lines in console</description>
- <version>0.1</version>
- <idea-version since-build="95.28"/>
- <vendor logo="/images/pluginIcon.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
-
- <extensionPoints>
- <extensionPoint qualifiedName="com.intellij.stacktrace.fold" beanClass="com.intellij.execution.CustomizableConsoleFoldingBean"/>
- </extensionPoints>
-
- <extensions defaultExtensionNs="com.intellij">
- <applicationService serviceInterface="com.intellij.execution.ConsoleFoldingSettings" serviceImplementation="com.intellij.execution.ConsoleFoldingSettings"/>
- <console.folding implementation="com.intellij.execution.SubstringConsoleFolding"/>
- <applicationConfigurable implementation="com.intellij.execution.ConsoleFoldingConfigurable"/>
-
- <!--<stacktrace.fold substring="at org.codehaus.groovy."/>
- <stacktrace.fold substring="at groovy."/>
- <stacktrace.fold substring="at groovy."/>
- <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethods." negate="true"/>
- <stacktrace.fold substring="at org.codehaus.groovy.vmplugin.v5.PluginDefaultGroovyMethods." negate="true"/>
- <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport." negate="true"/>
-
- <stacktrace.fold substring="at java.lang.reflect.Method.invoke("/>
- <stacktrace.fold substring="at java.lang.reflect.Constructor.newInstance("/>
- <stacktrace.fold substring="at sun.reflect."/>-->
-
- <stacktrace.fold substring="at org.junit.internal.runners."/>
-
- </extensions>
-
-</idea-plugin>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_4" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$/rt">
- <sourceFolder url="file://$MODULE_DIR$/rt/src" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="Groovy" level="project" />
- </component>
-</module>
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="module" module-name="lang-api" />
- <orderEntry type="module" module-name="jetgroovy" />
- <orderEntry type="module" module-name="openapi" />
- <orderEntry type="module" module-name="execution-openapi" />
- <orderEntry type="module" module-name="grape-rt" />
- </component>
-</module>
-
+++ /dev/null
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
- <id>org.intellij.groovy.grape</id>
- <name>Groovy Grape support</name>
- <description>An intention on @Grab annotations to download the needed dependencies</description>
- <version>0.4</version>
- <idea-version since-build="95.28"/>
- <vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
- <depends>org.intellij.groovy</depends>
-
- <extensions defaultExtensionNs="com.intellij">
- <intentionAction>
- <bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
- <categoryKey>intention.category.groovy</categoryKey>
- <className>org.jetbrains.plugins.groovy.grape.GrabDependencies</className>
- </intentionAction>
- </extensions>
-
-</idea-plugin>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="module" module-name="jetgroovy" />
- <orderEntry type="module" module-name="lang-api" />
- <orderEntry type="module" module-name="idea-ui" />
- <orderEntry type="module" module-name="openapi" />
- <orderEntry type="module" module-name="java-impl" />
- </component>
-</module>
-
+++ /dev/null
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
- <id>org.intellij.groovy.gpp</id>
- <name>Groovy++ Support</name>
- <description>Adds code assistance for the Groovy++ features</description>
- <version>0.1</version>
- <idea-version since-build="95.90" until-build="96.239"/>
- <vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
- <depends>org.intellij.groovy</depends>
-
- <extensions defaultExtensionNs="org.intellij.groovy">
- <libraryManager implementation="org.jetbrains.plugins.groovy.gpp.GppLibraryManager" order="first"/>
- <typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
- <expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
- <variableEnhancer implementation="org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider"/>
- <classSubstitutor implementation="org.jetbrains.plugins.groovy.gpp.GppClassSubstitutor"/>
- <nonCodeProcessor implementation="org.jetbrains.plugins.groovy.gpp.GppStdLibSupport"/>
- <positionManagerDelegate implementation="org.jetbrains.plugins.groovy.gpp.GppPositionManager"/>
- </extensions>
-
- <extensions defaultExtensionNs="com.intellij">
- <psi.referenceContributor implementation="org.jetbrains.plugins.groovy.gpp.GppReferenceContributor"/>
- </extensions>
-
-
-</idea-plugin>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/pluginSrc" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="asm" level="project" />
- <orderEntry type="module" module-name="debugger-impl" />
- <orderEntry type="module" module-name="annotations" />
- <orderEntry type="module" module-name="lang-api" />
- <orderEntry type="module" module-name="execution-openapi" />
- <orderEntry type="module" module-name="platform-impl" />
- <orderEntry type="module" module-name="jetgroovy" />
- <orderEntry type="module" module-name="lang-impl" />
- <orderEntry type="module" module-name="execution-impl" />
- <orderEntry type="module" module-name="openapi" />
- </component>
-</module>
-
+++ /dev/null
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
- <id>org.intellij.groovy.hotswap</id>
- <name>Groovy HotSwap</name>
- <description>Enables HotSwap functionality in Groovy classes</description>
- <version>0.6</version>
- <idea-version since-build="94.632"/>
- <vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
- <depends>org.intellij.groovy</depends>
-
- <extensions defaultExtensionNs="com.intellij">
- <java.programPatcher implementation="org.jetbrains.plugins.groovy.debugger.GroovyHotSwapper"/>
- </extensions>
-
-</idea-plugin>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module relativePaths="true" type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$/test">
- <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
- </content>
- <content url="file://$MODULE_DIR$/testdata" />
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="module" module-name="openapi" />
- <orderEntry type="module" module-name="xml" />
- <orderEntry type="module" module-name="debugger-openapi" />
- <orderEntry type="module" module-name="groovy-rt" />
- <orderEntry type="module" module-name="compiler-impl" />
- <orderEntry type="module" module-name="debugger-impl" />
- <orderEntry type="library" name="JUnit4" level="project" />
- <orderEntry type="module" module-name="lang-api" />
- <orderEntry type="module" module-name="properties" />
- <orderEntry type="module" module-name="execution-impl" />
- <orderEntry type="module" module-name="jetgroovy" />
- <orderEntry type="module" module-name="testFramework-java" />
- <orderEntry type="library" name="Groovy" level="project" />
- <orderEntry type="module" module-name="execution-openapi" />
- <orderEntry type="module" module-name="java-impl" />
- <orderEntry type="module" module-name="IntelliLang-java" />
- <orderEntry type="module" module-name="IntelliLang-xml" />
- <orderEntry type="module" module-name="groovypp" />
- </component>
-</module>
-
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="properties" />
<orderEntry type="module" module-name="execution-impl" />
- <orderEntry type="library" name="Ant" level="project" />
<orderEntry type="module" module-name="compiler-openapi" />
<orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="module" module-name="copyright" />
<orderEntry type="module" module-name="IntelliLangJava" />
<orderEntry type="module" module-name="ant" />
+ <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
</component>
</module>
<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
<id>org.intellij.groovy</id>
- <name>JetGroovy</name>
+ <name>Groovy</name>
<description>Plugin for Groovy language support</description>
<version>9.0</version>
<vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.
<membersContributor implementation="org.jetbrains.plugins.groovy.gant.GantMemberContributor"/>
- <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.GrContainerTypeConverter"/>
+ <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.GrContainerTypeConverter"/>
+
+ <libraryManager implementation="org.jetbrains.plugins.groovy.gpp.GppLibraryManager" order="first"/>
+ <typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
+ <expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
+ <variableEnhancer implementation="org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider"/>
+ <classSubstitutor implementation="org.jetbrains.plugins.groovy.gpp.GppClassSubstitutor"/>
+ <nonCodeProcessor implementation="org.jetbrains.plugins.groovy.gpp.GppStdLibSupport"/>
+ <positionManagerDelegate implementation="org.jetbrains.plugins.groovy.gpp.GppPositionManager"/>
+
</extensions>
<extensions defaultExtensionNs="com.intellij">
<patterns.patternClass className="org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns" alias="groovy"/>
+ <stacktrace.fold substring="at org.codehaus.groovy."/>
+ <stacktrace.fold substring="at groovy."/>
+ <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethods." negate="true"/>
+ <stacktrace.fold substring="at org.codehaus.groovy.vmplugin.v5.PluginDefaultGroovyMethods." negate="true"/>
+ <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport." negate="true"/>
+
<!-- control flow -->
<intentionAction>
<bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
<className>org.jetbrains.plugins.groovy.intentions.style.ReplaceAbstractClassInstanceByMapIntention</className>
</intentionAction>
+ <intentionAction>
+ <bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
+ <categoryKey>intention.category.groovy</categoryKey>
+ <className>org.jetbrains.plugins.groovy.grape.GrabDependencies</className>
+ </intentionAction>
+
+
<projectService serviceInterface="org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicToolWindowWrapper"
serviceImplementation="org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicToolWindowWrapper"/>
+
+ <java.programPatcher implementation="org.jetbrains.plugins.groovy.debugger.GroovyHotSwapper"/>
+ <psi.referenceContributor implementation="org.jetbrains.plugins.groovy.gpp.GppReferenceContributor"/>
</extensions>
<extensions defaultExtensionNs="com.intellij.debugger">
public static Set<String> getCustomGroovyScriptExtensions() {
final LinkedHashSet<String> strings = new LinkedHashSet<String>();
strings.add("gdsl");
+ strings.add("gpp");
+ strings.add("grunit");
for (GroovyScriptTypeEP ep : GroovyScriptType.EP_NAME.getExtensions()) {
ContainerUtil.addAll(strings, ep.extensions.split(";"));
}
final PsiFile file = e.getData(DataKeys.PSI_FILE);
assert file != null && file.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
+
+ doExcludeFromStubGeneration(file);
+ }
+
+ public static void doExcludeFromStubGeneration(PsiFile file) {
final VirtualFile virtualFile = file.getVirtualFile();
assert virtualFile != null;
final Project project = file.getProject();
configurable.getExcludes().addEntry(new ExcludeEntryDescription(virtualFile, false, true, project));
}
});
-
}
public void update(AnActionEvent e) {
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
+import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiClass;
+import com.intellij.ui.EditorNotificationPanel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.compiler.generator.GroovycStubGenerator;
compilerManager.addTranslatingCompiler(new GroovyCompiler(myProject),
new HashSet<FileType>(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.CLASS)),
new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
+
+ myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
+ @Override
+ public void fileOpened(FileEditorManager source, final VirtualFile file) {
+ if (file.getName().endsWith(".java") && file.getPath().contains(GroovycStubGenerator.GROOVY_STUBS)) {
+ final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
+ if (psiClass != null) {
+ final FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
+ final FileEditor[] editors = fileEditorManager.getEditors(file);
+ if (editors.length != 0) {
+ decorateStubFile(file, fileEditorManager, editors[0]);
+ }
+
+ }
+ }
+ }
+ });
+ }
+
+ private void decorateStubFile(final VirtualFile file, FileEditorManager fileEditorManager, FileEditor editor) {
+ final EditorNotificationPanel panel = new EditorNotificationPanel();
+ panel.setText("This stub is generated for Groovy class to make Groovy-Java cross-compilation possible");
+ panel.createActionLabel("Go to the Groovy class", new Runnable() {
+ @Override
+ public void run() {
+ final PsiClass original = GroovycStubGenerator.findClassByStub(myProject, file);
+ if (original != null) {
+ original.navigate(true);
+ }
+ }
+ });
+ panel.createActionLabel("Exclude from stub generation", new Runnable() {
+ @Override
+ public void run() {
+ final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
+ if (psiClass != null) {
+ ExcludeFromStubGenerationAction.doExcludeFromStubGeneration(psiClass.getContainingFile());
+ }
+ }
+ });
+ fileEditorManager.addTopComponent(editor, panel);
}
@NotNull
*/
package org.jetbrains.plugins.groovy.compiler.generator;
+import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightMethodBuilder;
import com.intellij.psi.util.MethodSignature;
+import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.MethodSignatureUtil;
+import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
+import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
}
for (final GrTypeDefinition typeDefinition : file.getTypeDefinitions()) {
- generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, typeDefinition, packageDefinition));
+ generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, GrClassSubstitutor.getSubstitutedClass(typeDefinition), packageDefinition));
}
return generatedItemsRelativePaths;
writePackageStatement(text, packageDefinition);
- GrMembersDeclaration[] membersDeclarations = typeDefinition instanceof GrTypeDefinition
- ? ((GrTypeDefinition)typeDefinition).getMemberDeclarations()
- : GrMembersDeclaration.EMPTY_ARRAY; //todo
-
- boolean isClassDef = typeDefinition instanceof GrClassDefinition;
- boolean isInterface = typeDefinition instanceof GrInterfaceDefinition;
- boolean isEnum = typeDefinition instanceof GrEnumTypeDefinition;
- boolean isAtInterface = typeDefinition instanceof GrAnnotationTypeDefinition;
+ boolean isEnum = typeDefinition.isEnum();
+ boolean isAnnotationType = typeDefinition.isAnnotationType();
+ boolean isInterface = !isAnnotationType && typeDefinition.isInterface();
+ boolean isClassDef = !isInterface && !isEnum && !isAnnotationType && !isScript;
writeClassModifiers(text, typeDefinition.getModifierList(), typeDefinition.isInterface(), toplevel);
if (isInterface) text.append("interface");
else if (isEnum) text.append("enum");
- else if (isAtInterface) text.append("@interface");
+ else if (isAnnotationType) text.append("@interface");
else text.append("class");
text.append(" ").append(typeDefinition.getName());
if (isScript) {
text.append("extends groovy.lang.Script ");
}
- else if (!isEnum && !isAtInterface) {
+ else if (!isEnum && !isAnnotationType) {
final PsiClassType[] extendsClassesTypes = typeDefinition.getExtendsListTypes();
if (extendsClassesTypes.length > 0) {
writeEnumConstants(text, (GrEnumTypeDefinition)typeDefinition);
}
- Set<MethodSignature> methodSignatures = new HashSet<MethodSignature>();
-
+ writeAllMethods(text, collectMethods(typeDefinition, isClassDef), typeDefinition);
- List<PsiMethod> methods = new ArrayList<PsiMethod>();
- ContainerUtil.addAll(methods, typeDefinition.getMethods());
- if (isClassDef) {
- final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
- methods.add(factory.createMethodFromText("public groovy.lang.MetaClass getMetaClass() {}", null));
- methods.add(factory.createMethodFromText("public void setMetaClass(groovy.lang.MetaClass mc) {}", null));
- methods.add(factory.createMethodFromText("public Object invokeMethod(String name, Object args) {}", null));
- methods.add(factory.createMethodFromText("public Object getProperty(String propertyName) {}", null));
- methods.add(factory.createMethodFromText("public void setProperty(String propertyName, Object newValue) {}", null));
+ if (typeDefinition instanceof GrTypeDefinition) {
+ for (GrMembersDeclaration declaration : ((GrTypeDefinition)typeDefinition).getMemberDeclarations()) {
+ if (declaration instanceof GrVariableDeclaration) {
+ writeVariableDeclarations(text, (GrVariableDeclaration)declaration);
+ }
+ }
+ }
+ for (PsiClass inner : typeDefinition.getInnerClasses()) {
+ writeTypeDefinition(text, inner, null, false);
+ text.append("\n");
}
+ text.append("}");
+ }
+ private static void writeAllMethods(StringBuffer text, List<PsiMethod> methods, PsiClass aClass) {
+ Set<MethodSignature> methodSignatures = new HashSet<MethodSignature>();
for (PsiMethod method : methods) {
if (LightMethodBuilder.isLightMethod(method, GrClassImplUtil.SYNTHETIC_METHOD_IMPLEMENTATION)) {
continue;
}
if (method instanceof GrConstructor) {
- writeConstructor(text, (GrConstructor)method, isEnum);
+ writeConstructor(text, (GrConstructor)method, aClass.isEnum());
continue;
}
}
}
}
+ }
- for (GrMembersDeclaration declaration : membersDeclarations) {
- if (declaration instanceof GrVariableDeclaration) {
- writeVariableDeclarations(text, (GrVariableDeclaration)declaration);
+ private List<PsiMethod> collectMethods(PsiClass typeDefinition, boolean classDef) {
+ List<PsiMethod> methods = new ArrayList<PsiMethod>();
+ ContainerUtil.addAll(methods, typeDefinition.getMethods());
+ if (classDef) {
+ final Collection<MethodSignature> toOverride = OverrideImplementUtil.getMethodSignaturesToOverride(typeDefinition);
+ for (MethodSignature signature : toOverride) {
+ if (signature instanceof MethodSignatureBackedByPsiMethod) {
+ final PsiMethod method = ((MethodSignatureBackedByPsiMethod)signature).getMethod();
+ final PsiClass baseClass = method.getContainingClass();
+ if (isAbstractInJava(method) && baseClass != null && typeDefinition.isInheritor(baseClass, true)) {
+ final LightMethodBuilder builder = new LightMethodBuilder(method.getManager(), method.getName());
+ final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, typeDefinition, PsiSubstitutor.EMPTY);
+ for (PsiParameter parameter : method.getParameterList().getParameters()) {
+ builder.addParameter(parameter.getName(), substitutor.substitute(parameter.getType()));
+ }
+ builder.setReturnType(substitutor.substitute(method.getReturnType()));
+ for (String modifier : JAVA_MODIFIERS) {
+ if (method.hasModifierProperty(modifier)) {
+ builder.addModifier(modifier);
+ }
+ }
+ methods.add(builder);
+ }
+ }
}
+
+ final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
+ methods.add(factory.createMethodFromText("public groovy.lang.MetaClass getMetaClass() {}", null));
+ methods.add(factory.createMethodFromText("public void setMetaClass(groovy.lang.MetaClass mc) {}", null));
+ methods.add(factory.createMethodFromText("public Object invokeMethod(String name, Object args) {}", null));
+ methods.add(factory.createMethodFromText("public Object getProperty(String propertyName) {}", null));
+ methods.add(factory.createMethodFromText("public void setProperty(String propertyName, Object newValue) {}", null));
}
- for (PsiClass inner : typeDefinition.getInnerClasses()) {
- writeTypeDefinition(text, inner, null, false);
- text.append("\n");
+ return methods;
+ }
+
+ private static boolean isAbstractInJava(PsiMethod method) {
+ if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ return true;
}
- text.append("}");
+ final PsiClass psiClass = method.getContainingClass();
+ return psiClass != null && GrClassSubstitutor.getSubstitutedClass(psiClass).isInterface();
}
private static void appendTypeParameters(StringBuffer text, PsiTypeParameterListOwner typeParameterListOwner) {
if (!JavaPsiFacade.getInstance(method.getProject()).getNameHelper().isIdentifier(name))
return; //does not have a java image
- boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
+ boolean isAbstract = isAbstractInJava(method);
PsiModifierList modifierList = method.getModifierList();
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerBase;
import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
*/
public class GroovycStubGenerator extends GroovyCompilerBase {
+ public static final String GROOVY_STUBS = "groovyStubs";
+
public GroovycStubGenerator(Project project) {
super(project);
}
@Override
protected void compileFiles(CompileContext compileContext, Module module,
final List<VirtualFile> toCompile, OutputSink sink, boolean tests) {
- final String rootPath = CompilerPaths.getGeneratedDataDirectory(myProject) + "/groovyStubs/";
- final File outDir = new File(rootPath + myProject.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
+ final File outDir = getStubOutput(module, tests);
outDir.mkdirs();
final VirtualFile tempOutput = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(outDir);
}
}
+ private static File getStubOutput(Module module, boolean tests) {
+ final Project project = module.getProject();
+ final String rootPath = CompilerPaths.getGeneratedDataDirectory(project).getPath() + "/" + GROOVY_STUBS + "/";
+ return new File(rootPath + project.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
+ }
+
+ @Nullable
+ public static PsiClass findClassByStub(Project project, VirtualFile stubFile) {
+ final String[] components = StringUtil.trimEnd(stubFile.getPath(), ".java").split("[\\\\/]");
+ final int stubs = Arrays.asList(components).indexOf(GROOVY_STUBS);
+ if (stubs < 0 || stubs >= components.length - 4) return null;
+
+ final String moduleName = components[stubs + 2];
+ final Module module = ModuleManager.getInstance(project).findModuleByName(moduleName);
+ if (module == null) return null;
+
+ final String fqn = StringUtil.join(Arrays.asList(components).subList(stubs + 4, components.length), ".");
+ return JavaPsiFacade.getInstance(project).findClass(fqn, GlobalSearchScope.moduleScope(module));
+ }
+
private void cleanDirectory(final VirtualFile dir) {
new WriteCommandAction(myProject) {
protected void run(Result result) throws Throwable {
@Override
public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
if (rType instanceof GrTupleType) {
- final PsiType type = PsiUtil.extractIterableTypeParameter(lType, false);
- if (type == null || TypesUtil.isAssignable(type, ((GrTupleType)rType).getParameters()[0], context)) {
- final PsiType[] componentTypes = ((GrTupleType)rType).getComponentTypes();
-
- final PsiType expectedComponent = PsiUtil.extractIterableTypeParameter(lType, false);
- if (expectedComponent != null && hasDefaultConstructor(lType)) {
- return true;
- }
-
- if (lType instanceof PsiClassType && hasConstructor((PsiClassType)lType, componentTypes, context)) {
- return true;
- }
+ final GrTupleType tupleType = (GrTupleType)rType;
+
+ final PsiType expectedComponent = PsiUtil.extractIterableTypeParameter(lType, false);
+ if (expectedComponent != null &&
+ isMethodCallConversion(context) && TypesUtil.isAssignable(expectedComponent, tupleType.getParameters()[0], context) &&
+ hasDefaultConstructor(lType)) {
+ return true;
+ }
+
+ if (lType instanceof PsiClassType && hasConstructor((PsiClassType)lType, tupleType.getComponentTypes(), context)) {
+ return true;
}
}
else if (rType instanceof GrMapType) {
}
else if (call instanceof GrCallExpression) {
GrCallExpression constructorCall = (GrCallExpression)call;
- ContainerUtil.addAll(results, constructorCall.getMethodVariants());
+ ContainerUtil.addAll(results, constructorCall.getMethodVariants(null));
final PsiType type = ((GrCallExpression)call).getType();
if (type instanceof PsiClassType) {
final PsiClass psiClass = ((PsiClassType)type).resolve();
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
/**
* @author peter
public abstract class GrTypeConverter {
public static final ExtensionPointName<GrTypeConverter> EP_NAME = ExtensionPointName.create("org.intellij.groovy.typeConverter");
+ protected static boolean isMethodCallConversion(GroovyPsiElement context) {
+ return context.getParent() instanceof GrMethodCall;
+ }
+
@Nullable
public abstract Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context);
-}
\ No newline at end of file
+}
PsiMethod resolveMethod();
@NotNull
- GroovyResolveResult[] getMethodVariants();
+ GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument);
//PsiElement addNamedArgument(GrNamedArgument argument);
}
final int closureIndex = closureArgs.indexOf(myExpression);
if (closureIndex >= 0) {
List<TypeConstraint> constraints = new ArrayList<TypeConstraint>();
- for (GroovyResolveResult variant : methodCall.getMethodVariants()) {
+ for (GroovyResolveResult variant : ResolveUtil.getMethodVariants(myExpression)) {
PsiParameter[] parameters = getCallParameters(variant);
if (parameters == null || parameters.length == 0) continue;
public class GrContainerTypeConverter extends GrTypeConverter {
@Override
public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
+ if (isMethodCallConversion(context)) {
+ return null;
+ }
+
if (!isCollectionOrArray(lType) || !isCollectionOrArray(rType)) return null;
final PsiType lComponentType = extractComponentType(lType);
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
components.add(getInternalCanonicalText(entry.first) + ":" + getInternalCanonicalText(entry.second));
}
- return "[" + StringUtil.join(components, ", ") + "]";
+ boolean tooMany = components.size() > 2;
+ final List<String> theFirst = components.subList(0, Math.min(2, components.size()));
+ return "[" + StringUtil.join(theFirst, ", ") + (tooMany ? ",..." : "") + "]";
}
public boolean isValid() {
StringBuilder builder = new StringBuilder();
builder.append("[");
for (int i = 0; i < myComponentTypes.length; i++) {
+ if (i >= 2) {
+ builder.append(",...");
+ break;
+ }
+
if (i > 0) builder.append(", ");
builder.append(getInternalCanonicalText(myComponentTypes[i]));
}
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
}
@NotNull
- public GroovyResolveResult[] getMethodVariants() {
+ public GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument) {
final GrCodeReferenceElement referenceElement = getReferenceElement();
if (referenceElement == null) return GroovyResolveResult.EMPTY_ARRAY;
final GroovyResolveResult[] classResults = referenceElement.multiResolve(false);
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Consumer;
+import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.resolve.processors.*;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
Kind kind = refExpr.getKind();
if (incompleteCode) {
ResolverProcessor processor = CompletionProcessor.createRefSameNameProcessor(refExpr, name);
- resolveImpl(refExpr, processor);
+ refExpr.resolveImpl(processor);
GroovyResolveResult[] propertyCandidates = processor.getCandidates();
if (propertyCandidates.length > 0) return propertyCandidates;
}
GroovyResolveResult[] classCandidates = GroovyResolveResult.EMPTY_ARRAY;
if (!hasAt) {
ResolverProcessor classProcessor = new ClassResolverProcessor(refExpr.getReferenceName(), refExpr, kinds);
- resolveImpl(refExpr, classProcessor);
+ refExpr.resolveImpl(classProcessor);
classCandidates = classProcessor.getCandidates();
for (GroovyResolveResult classCandidate : classCandidates) {
final PsiElement element = classCandidate.getElement();
}
ResolverProcessor processor = new PropertyResolverProcessor(name, refExpr);
- resolveImpl(refExpr, processor);
+ refExpr.resolveImpl(processor);
final GroovyResolveResult[] fieldCandidates = processor.getCandidates();
if (refExpr.hasAt()) {
List<GroovyResolveResult> accessorResults = new ArrayList<GroovyResolveResult>();
for (String getterName : names) {
AccessorResolverProcessor accessorResolver = new AccessorResolverProcessor(getterName, refExpr, !isLValue);
- resolveImpl(refExpr, accessorResolver);
+ refExpr.resolveImpl(accessorResolver);
final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); //can be only one candidate
if (candidates.length == 1 && candidates[0].isStaticsOK()) {
return candidates;
private static GroovyResolveResult[] resolveMethodOrProperty(GrReferenceExpressionImpl refExpr, String name) {
final PsiType[] argTypes = PsiUtil.getArgumentTypes(refExpr, false);
- PsiType thisType = getThisType(refExpr);
-
- MethodResolverProcessor methodResolver =
- new MethodResolverProcessor(name, refExpr, false, thisType, argTypes, refExpr.getTypeArguments());
- resolveImpl(refExpr, methodResolver);
+ MethodResolverProcessor methodResolver = refExpr.runMethodResolverProcessor(argTypes, false);
+ assert methodResolver != null;
if (methodResolver.hasApplicableCandidates()) return methodResolver.getCandidates();
final String[] names = GroovyPropertyUtils.suggestGettersName(name);
List<GroovyResolveResult> list = new ArrayList<GroovyResolveResult>();
for (String getterName : names) {
AccessorResolverProcessor getterResolver = new AccessorResolverProcessor(getterName, refExpr, true);
- resolveImpl(refExpr, getterResolver);
+ refExpr.resolveImpl(getterResolver);
final GroovyResolveResult[] candidates = getterResolver.getCandidates(); //can be only one candidate
if (candidates.length == 1 && candidates[0].isStaticsOK()) {
refExpr.putUserData(IS_RESOLVED_TO_GETTER, true);
}
PropertyResolverProcessor propertyResolver = new PropertyResolverProcessor(name, refExpr);
- resolveImpl(refExpr, propertyResolver);
+ refExpr.resolveImpl(propertyResolver);
if (propertyResolver.hasCandidates()) return propertyResolver.getCandidates();
if (methodResolver.hasCandidates()) {
return GroovyResolveResult.EMPTY_ARRAY;
}
+ }
- private static void resolveImpl(GrReferenceExpressionImpl refExpr, ResolverProcessor processor) {
- GrExpression qualifier = refExpr.getQualifierExpression();
- if (qualifier == null) {
- ResolveUtil.treeWalkUp(refExpr, processor, true);
- if (!processor.hasCandidates()) {
- qualifier = PsiImplUtil.getRuntimeQualifier(refExpr);
- if (qualifier != null) {
- processQualifier(refExpr, processor, qualifier);
- }
+ private void resolveImpl(ResolverProcessor processor) {
+ GrExpression qualifier = getQualifierExpression();
+ if (qualifier == null) {
+ ResolveUtil.treeWalkUp(this, processor, true);
+ if (!processor.hasCandidates()) {
+ qualifier = PsiImplUtil.getRuntimeQualifier(this);
+ if (qualifier != null) {
+ processQualifier(processor, qualifier);
}
+ }
+ } else {
+ if (getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
+ processQualifier(processor, qualifier);
} else {
- if (refExpr.getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
- processQualifier(refExpr, processor, qualifier);
- } else {
- processQualifierForSpreadDot(refExpr, processor, qualifier);
- }
+ processQualifierForSpreadDot(processor, qualifier);
+ }
- if (qualifier instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)qualifier).getReferenceName())) {
- processIfJavaLangClass(refExpr, processor, qualifier.getType());
- } else if (qualifier instanceof GrThisReferenceExpression) {
- processIfJavaLangClass(refExpr, processor, qualifier.getType());
- }
+ if (qualifier instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)qualifier).getReferenceName())) {
+ processIfJavaLangClass(processor, qualifier.getType());
+ } else if (qualifier instanceof GrThisReferenceExpression) {
+ processIfJavaLangClass(processor, qualifier.getType());
}
}
+ }
- private static void processIfJavaLangClass(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, PsiType type) {
- if (type instanceof PsiClassType) {
- final PsiClass psiClass = ((PsiClassType)type).resolve();
- if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
- final PsiType[] params = ((PsiClassType)type).getParameters();
- if (params.length == 1) {
- processClassQualifierType(refExpr, processor, params[0]);
- }
+ private void processIfJavaLangClass(ResolverProcessor processor, PsiType type) {
+ if (type instanceof PsiClassType) {
+ final PsiClass psiClass = ((PsiClassType)type).resolve();
+ if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
+ final PsiType[] params = ((PsiClassType)type).getParameters();
+ if (params.length == 1) {
+ processClassQualifierType(processor, params[0]);
}
}
}
+ }
- private static void processQualifierForSpreadDot(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, GrExpression qualifier) {
- PsiType qualifierType = qualifier.getType();
- if (qualifierType instanceof PsiClassType) {
- PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics();
- PsiClass clazz = result.getElement();
- if (clazz != null) {
- PsiClass listClass = ResolveUtil.findListClass(refExpr.getManager(), refExpr.getResolveScope());
- if (listClass != null && listClass.getTypeParameters().length == 1) {
- PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(listClass, clazz, result.getSubstitutor());
- if (substitutor != null) {
- PsiType componentType = substitutor.substitute(listClass.getTypeParameters()[0]);
- if (componentType != null) {
- processClassQualifierType(refExpr, processor, componentType);
- }
+ private void processQualifierForSpreadDot(ResolverProcessor processor, GrExpression qualifier) {
+ PsiType qualifierType = qualifier.getType();
+ if (qualifierType instanceof PsiClassType) {
+ PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics();
+ PsiClass clazz = result.getElement();
+ if (clazz != null) {
+ PsiClass listClass = ResolveUtil.findListClass(getManager(), getResolveScope());
+ if (listClass != null && listClass.getTypeParameters().length == 1) {
+ PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(listClass, clazz, result.getSubstitutor());
+ if (substitutor != null) {
+ PsiType componentType = substitutor.substitute(listClass.getTypeParameters()[0]);
+ if (componentType != null) {
+ processClassQualifierType(processor, componentType);
}
}
}
- } else if (qualifierType instanceof PsiArrayType) {
- processClassQualifierType(refExpr, processor, ((PsiArrayType) qualifierType).getComponentType());
}
+ } else if (qualifierType instanceof PsiArrayType) {
+ processClassQualifierType(processor, ((PsiArrayType) qualifierType).getComponentType());
}
+ }
- private static void processQualifier(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, GrExpression qualifier) {
- PsiType qualifierType = qualifier.getType();
- if (qualifierType == null) {
- if (qualifier instanceof GrReferenceExpression) {
- PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
- if (resolved instanceof PsiPackage) {
- if (!resolved.processDeclarations(processor, ResolveState.initial(), null, refExpr)) //noinspection UnnecessaryReturnStatement
- return;
- }
- else {
- qualifierType = JavaPsiFacade.getInstance(refExpr.getProject()).getElementFactory()
- .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, refExpr.getResolveScope());
- processClassQualifierType(refExpr, processor, qualifierType);
- }
+ private void processQualifier(ResolverProcessor processor, GrExpression qualifier) {
+ PsiType qualifierType = qualifier.getType();
+ if (qualifierType == null) {
+ if (qualifier instanceof GrReferenceExpression) {
+ PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
+ if (resolved instanceof PsiPackage) {
+ if (!resolved.processDeclarations(processor, ResolveState.initial(), null, this)) //noinspection UnnecessaryReturnStatement
+ return;
+ }
+ else {
+ qualifierType = JavaPsiFacade.getInstance(getProject()).getElementFactory()
+ .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, getResolveScope());
+ processClassQualifierType(processor, qualifierType);
+ }
+ }
+ } else {
+ if (qualifierType instanceof PsiIntersectionType) {
+ for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
+ processClassQualifierType(processor, conjunct);
}
} else {
- if (qualifierType instanceof PsiIntersectionType) {
- for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
- processClassQualifierType(refExpr, processor, conjunct);
- }
- } else {
- processClassQualifierType(refExpr, processor, qualifierType);
- if (qualifier instanceof GrReferenceExpression) {
- PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
- if (resolved instanceof PsiClass) { //omitted .class
- PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, refExpr.getResolveScope());
- if (javaLangClass != null) {
- ResolveState state = ResolveState.initial();
- PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
- PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
- if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
- if (typeParameters.length == 1) {
- substitutor = substitutor.put(typeParameters[0], qualifierType);
- state = state.put(PsiSubstitutor.KEY, substitutor);
- }
- if (!javaLangClass.processDeclarations(processor, state, null, refExpr)) return;
- PsiType javaLangClassType = JavaPsiFacade.getInstance(refExpr.getProject()).getElementFactory().createType(javaLangClass, substitutor);
- ResolveUtil.processNonCodeMethods(javaLangClassType, processor, refExpr, false);
+ processClassQualifierType(processor, qualifierType);
+ if (qualifier instanceof GrReferenceExpression) {
+ PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
+ if (resolved instanceof PsiClass) { //omitted .class
+ PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, getResolveScope());
+ if (javaLangClass != null) {
+ ResolveState state = ResolveState.initial();
+ PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
+ PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
+ if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
+ if (typeParameters.length == 1) {
+ substitutor = substitutor.put(typeParameters[0], qualifierType);
+ state = state.put(PsiSubstitutor.KEY, substitutor);
}
+ if (!javaLangClass.processDeclarations(processor, state, null, this)) return;
+ PsiType javaLangClassType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createType(javaLangClass, substitutor);
+ ResolveUtil.processNonCodeMethods(javaLangClassType, processor, this, false);
}
}
}
}
}
+ }
- private static void processClassQualifierType(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, PsiType qualifierType) {
- Project project = refExpr.getProject();
- if (qualifierType instanceof PsiClassType) {
- PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType) qualifierType).resolveGenerics();
- PsiClass qualifierClass = qualifierResult.getElement();
- if (qualifierClass != null) {
- if (!qualifierClass.processDeclarations(processor,
- ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, refExpr))
- return;
- }
- if (!ResolveUtil.processCategoryMembers(refExpr, processor)) return;
- } else if (qualifierType instanceof PsiArrayType) {
- final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass();
- if (!arrayClass.processDeclarations(processor, ResolveState.initial(), null, refExpr)) return;
- } else if (qualifierType instanceof PsiIntersectionType) {
- for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
- processClassQualifierType(refExpr, processor, conjunct);
- }
- return;
+ private void processClassQualifierType(ResolverProcessor processor, PsiType qualifierType) {
+ Project project = getProject();
+ if (qualifierType instanceof PsiClassType) {
+ PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType) qualifierType).resolveGenerics();
+ PsiClass qualifierClass = qualifierResult.getElement();
+ if (qualifierClass != null) {
+ if (!qualifierClass.processDeclarations(processor,
+ ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, this))
+ return;
+ }
+ if (!ResolveUtil.processCategoryMembers(this, processor)) return;
+ } else if (qualifierType instanceof PsiArrayType) {
+ final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass();
+ if (!arrayClass.processDeclarations(processor, ResolveState.initial(), null, this)) return;
+ } else if (qualifierType instanceof PsiIntersectionType) {
+ for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
+ processClassQualifierType(processor, conjunct);
}
+ return;
+ }
- ResolveUtil.processNonCodeMethods(qualifierType, processor, refExpr, false);
+ ResolveUtil.processNonCodeMethods(qualifierType, processor, this, false);
+ }
+
+ @Nullable
+ public MethodResolverProcessor runMethodResolverProcessor(PsiType[] argTypes, final boolean allVariants) {
+ final String name = getReferenceName();
+ if (name == null) {
+ return null;
}
+
+ PsiType thisType = getThisType();
+
+ MethodResolverProcessor methodResolver = new MethodResolverProcessor(name, this, false, thisType, argTypes, getTypeArguments(), allVariants);
+ resolveImpl(methodResolver);
+ return methodResolver;
}
- private static PsiType getThisType(GrReferenceExpression refExpr) {
- GrExpression qualifier = refExpr.getQualifierExpression();
+ private PsiType getThisType() {
+ GrExpression qualifier = getQualifierExpression();
if (qualifier != null) {
PsiType qType = qualifier.getType();
if (qType != null) return qType;
}
- return TypesUtil.getJavaLangObject(refExpr);
+ return TypesUtil.getJavaLangObject(this);
}
}
public static boolean isAssignable(PsiType lType, PsiType rType, GroovyPsiElement context, boolean allowConversion) {
+ if (rType instanceof PsiIntersectionType) {
+ for (PsiType child : ((PsiIntersectionType)rType).getConjuncts()) {
+ if (isAssignable(lType, child, context, allowConversion)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (lType instanceof PsiIntersectionType) {
+ for (PsiType child : ((PsiIntersectionType)lType).getConjuncts()) {
+ if (!isAssignable(child, rType, context, allowConversion)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
if (allowConversion && lType != null && rType != null) {
for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) {
final Boolean result = converter.isConvertible(lType, rType, context);
}
public static boolean isAssignableByMethodCallConversion(PsiType lType, PsiType rType, GroovyPsiElement context) {
- return isAssignableByMethodCallConversion(lType, rType, context.getManager(), context.getResolveScope());
+ if (lType == null || rType == null) return false;
+
+ if (isAssignableByMethodCallConversion(lType, rType, context.getManager(), context.getResolveScope())) {
+ return true;
+ }
+
+ for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) {
+ final Boolean result = converter.isConvertible(lType, rType, context);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return false;
}
public static boolean isAssignableByMethodCallConversion(PsiType lType, PsiType rType, PsiManager manager, GlobalSearchScope scope) {
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
import java.util.ArrayList;
-import java.util.Arrays;
/**
* @author ilyas
}
@NotNull
- public GroovyResolveResult[] getMethodVariants() {
+ public GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument) {
final GrExpression invoked = getInvokedExpression();
- if (!(invoked instanceof GrReferenceExpression)) return GroovyResolveResult.EMPTY_ARRAY;
- final ArrayList<GroovyResolveResult> res = new ArrayList<GroovyResolveResult>();
-
- for (PsiReference ref : invoked.getReferences()) {
- if (ref instanceof PsiPolyVariantReference) {
- for (ResolveResult result : ((PsiPolyVariantReference)ref).multiResolve(true)) {
- if (result instanceof GroovyResolveResult) {
- res.add((GroovyResolveResult)result);
- }
- }
- }
+ if (!(invoked instanceof GrReferenceExpressionImpl)) return GroovyResolveResult.EMPTY_ARRAY;
+
+ final PsiType[] partialArgs = PsiUtil.getArgumentTypes(invoked, false, upToArgument);
+ final MethodResolverProcessor processor = ((GrReferenceExpressionImpl)invoked).runMethodResolverProcessor(partialArgs, true);
+ if (processor != null) {
+ return processor.getCandidates();
}
- return res.toArray(new GroovyResolveResult[res.size()]);
+
+ return GroovyResolveResult.EMPTY_ARRAY;
}
}
public GroovyMethodCallPattern methodCall(final ElementPattern<? extends PsiMethod> method) {
return new GroovyMethodCallPattern().and(this).with(new PatternCondition<GrCallExpression>("methodCall") {
public boolean accepts(@NotNull GrCallExpression callExpression, ProcessingContext context) {
- final GroovyResolveResult[] results = callExpression.getMethodVariants();
+ final GroovyResolveResult[] results = callExpression.getMethodVariants(null);
for (GroovyResolveResult result : results) {
if (method.getCondition().accepts(result.getElement(), context)) {
return true;
}
}
-}
\ No newline at end of file
+}
@Nullable
public static PsiType[] getArgumentTypes(PsiElement place, boolean nullAsBottom) {
+ return getArgumentTypes(place, nullAsBottom, null);
+ }
+ @Nullable
+ public static PsiType[] getArgumentTypes(PsiElement place, boolean nullAsBottom, @Nullable GrExpression stopAt) {
PsiElement parent = place.getParent();
if (parent instanceof GrCallExpression) {
List<PsiType> result = new ArrayList<PsiType>();
} else {
result.add(type);
}
+ if (stopAt == expression) {
+ return result.toArray(new PsiType[result.size()]);
+ }
}
GrClosableBlock[] closures = call.getClosureArguments();
if (closureType != null) {
result.add(closureType);
}
+ if (stopAt == closure) {
+ break;
+ }
}
return result.toArray(new PsiType[result.size()]);
} else {
result.add(type);
}
+ if (stopAt == expression) {
+ break;
+ }
}
return result.toArray(new PsiType[result.size()]);
else {
result.add(argType);
}
+ if (stopAt == arg) {
+ break;
+ }
+
}
return result.toArray(new PsiType[result.size()]);
} else if (parent instanceof GrConstructorInvocation || parent instanceof GrEnumConstant) {
} else {
result.add(type);
}
+ if (stopAt == expression) {
+ break;
+ }
+
}
return result.toArray(new PsiType[result.size()]);
}
public static boolean isRawMethodCall(GrMethodCallExpression call) {
- final GroovyResolveResult[] resolveResults = call.getMethodVariants();
+ final GroovyResolveResult[] resolveResults = call.getMethodVariants(null);
if (resolveResults.length == 0) return false;
final PsiElement element = resolveResults[0].getElement();
if (element instanceof PsiMethod) {
final PsiElement parent = place.getParent();
GroovyResolveResult[] variants = GroovyResolveResult.EMPTY_ARRAY;
if (parent instanceof GrCallExpression) {
- variants = ((GrCallExpression) parent).getMethodVariants();
+ variants = ((GrCallExpression) parent).getMethodVariants(place instanceof GrExpression ? (GrExpression)place : null);
} else if (parent instanceof GrConstructorInvocation) {
final PsiClass clazz = ((GrConstructorInvocation) parent).getDelegatedClass();
if (clazz != null) {
@Nullable
private final PsiType[] myArgumentTypes;
private final PsiType[] myTypeArguments;
+ private final boolean myAllVariants;
private final Set<GroovyResolveResult> myInapplicableCandidates = new LinkedHashSet<GroovyResolveResult>();
private final boolean myIsConstructor;
private boolean myStopExecuting = false;
public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments) {
+ this(name, place, isConstructor, thisType, argumentTypes, typeArguments, false);
+ }
+ public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments, boolean allVariants) {
super(name, EnumSet.of(ResolveKind.METHOD, ResolveKind.PROPERTY), place, PsiType.EMPTY_ARRAY);
myIsConstructor = isConstructor;
myThisType = thisType;
myArgumentTypes = argumentTypes;
myTypeArguments = typeArguments;
+ myAllVariants = allVariants;
}
public boolean execute(PsiElement element, ResolveState state) {
boolean isAccessible = isAccessible(method);
GroovyPsiElement fileResolveContext = state.get(RESOLVE_CONTEXT);
boolean isStaticsOK = isStaticsOK(method, fileResolveContext);
- if (PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace) && isStaticsOK) {
+ if (!myAllVariants && PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace) && isStaticsOK) {
myCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
} else {
myInapplicableCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
@NotNull
public GroovyResolveResult[] getCandidates() {
+ if (myAllVariants) {
+ return myInapplicableCandidates.toArray(new GroovyResolveResult[myInapplicableCandidates.size()]);
+ }
+
if (!myCandidates.isEmpty()) {
return filterCandidates();
}
--- /dev/null
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.plugins.groovy.compiler;
+
+
+import com.intellij.testFramework.PsiTestUtil
+import org.jetbrains.plugins.groovy.util.TestUtils
+
+/**
+ * @author peter
+ */
+public class GppCompilerTest extends GroovyCompilerTestCase {
+ @Override protected void setUp() {
+ super.setUp();
+ PsiTestUtil.addLibrary myFixture.module, "gpp", TestUtils.absoluteTestDataPath + "/realGroovypp/", "groovypp-all-0.2.13.jar"
+ }
+
+ public void testTraitStubs() throws Throwable {
+ myFixture.addFileToProject("A.groovy", """
+@Trait
+abstract class SomeTrait {
+ abstract def some()
+ def concrete() {}
+}
+
+@Trait
+abstract class AnotherTrait extends SomeTrait {
+ abstract def another()
+}
+
+class Goo implements SomeTrait {
+ def some() {}
+}
+class Bar implements AnotherTrait {
+ def some() {}
+ def another() {}
+}
+""");
+ myFixture.addClass("""
+class Foo implements SomeTrait {
+ public Object some() { return null; }
+ public Object concrete() { return null; }
+}""")
+ assertEmpty(make());
+ }
+
+}
* @author peter
*/
public class GroovyCompilerTest extends GroovyCompilerTestCase {
+ @Override protected void setUp() {
+ super.setUp();
+ addGroovyLibrary(myModule, getName().contains("1_7"));
+ }
public void testPlainGroovy() throws Throwable {
myFixture.addFileToProject("A.groovy", "println '239'");
CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(myMainOutput.findOrCreateDir("out").getUrl());
}
}.execute();
-
- addGroovyLibrary(myModule, getName().contains("1_7"));
}
@Override
super.setUp()
}
- public void _testCastListToIterable() throws Exception {
+ public void testCastListToIterable() throws Exception {
myFixture.addClass("class X extends java.util.ArrayList<Integer> {}")
testAssignability """
X ints = [239, 4.2d]
"""
}
- public void _testCastListToAnything() throws Exception {
+ public void testCastListToAnything() throws Exception {
testAssignability """
File f1 = ['path']
-File f2 = <warning descr="Cannot assign 'List' to 'File'">['path', 2, true, 42]</warning>
+File f2 = <warning descr="Cannot assign 'List<Serializable>' to 'File'">['path', 2, true, 42]</warning>
"""
}
return myFixture.file.findReferenceAt(myFixture.editor.caretModel.offset).resolve()
}
- public void _testMethodTypeParameterInference() throws Exception {
+ public void testMethodTypeParameterInference() throws Exception {
configureScript """
@Typed package aaa
assertSameElements myFixture.getLookupElementStrings(), "intValue"
}
- public void _testMethodTypeParameterInference2() throws Exception {
+ public void testMethodTypeParameterInference2() throws Exception {
configureScript """
@Typed package aaa
modifiableModel.addRoot(JarFileSystem.instance.refreshAndFindFileByPath(TestUtils.mockGroovy1_7LibraryName + "!/"), OrderRootType.CLASSES);
modifiableModel.commit();
}
-}
\ No newline at end of file
+}
def foo(int... i) {}
def list = [1, 2, 3]
-foo<warning descr="'foo' in 'SignatureIsNotApplicableToList' cannot be applied to '([java.lang.Integer, java.lang.Integer, java.lang.Integer])'">(list)</warning>
\ No newline at end of file
+foo<warning descr="'foo' in 'SignatureIsNotApplicableToList' cannot be applied to '([java.lang.Integer, java.lang.Integer,...])'">(list)</warning>
\ No newline at end of file
<testFramework implementation="com.intellij.execution.junit.JUnit3Framework"/>
<testFramework implementation="com.intellij.execution.junit.JUnit4Framework"/>
<configurationType implementation="com.intellij.execution.junit.JUnitConfigurationType"/>
+ <stacktrace.fold substring="at org.junit.internal.runners."/>
</extensions>
<extensionPoints>
}
public void writeExternal(Element element) throws WriteExternalException {
- DefaultJDOMExternalizer.writeExternal(this, element);
+ if (!ADD_JUNIT_TO_ENTRIES) {
+ DefaultJDOMExternalizer.writeExternal(this, element);
+ }
}
}
\ No newline at end of file
* User: sweinreuter
* Date: 25.07.2007
*/
-public class XmlHighlightingTest extends HighlightingTestBase {
+public class RngXmlHighlightingTest extends HighlightingTestBase {
public String getTestDataPath() {
return "highlighting";
* User: sweinreuter
* Date: 25.07.2007
*/
-public class XmlValidationTest extends HighlightingTestBase {
+public class RngXmlValidationTest extends HighlightingTestBase {
public void testValidDocument() throws Throwable {
doTest("xslt.rng");
}
public void writeExternal(Element element) throws WriteExternalException {
- DefaultJDOMExternalizer.writeExternal(this, element);
+ if (!ADD_TESTNG_TO_ENTRIES) {
+ DefaultJDOMExternalizer.writeExternal(this, element);
+ }
}
@Nullable
protected void run(Result result) throws Throwable {
final int index = ns.length() + 1;
for (XmlTag tag : tags) {
- tag.setName(tag.getName().substring(index));
+ final String s = tag.getName().substring(index);
+ if (s.length() > 0) {
+ tag.setName(s);
+ }
}
for (XmlAttribute attr : attrs) {
attr.setValue(attr.getValue().substring(index));
}
else if (c == '\'') inApostrophes = false;
}
- else if (i == n - 1 || (i < n - 2 && DELIMS.indexOf(c) >= 0)) {
+ else if (i == n - 1 || (i < n - 2 && DELIMS.indexOf(c) >= 0) || c == ')') {
String key = templateKeyBuilder.toString();
templateKeyBuilder = new StringBuilder();
int num = parseNonNegativeInt(key);
}
else {
TemplateToken token = parseTemplateKey(key, callback);
- if (token == null) return null;
- result.add(token);
+ if (token != null) {
+ result.add(token);
+ }
}
if (i == n - 1) {
result.add(new MarkerToken());
package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlText;
import com.intellij.util.IncorrectOperationException;
public class XmlTextManipulator extends AbstractElementManipulator<XmlText> {
public XmlText handleContentChange(XmlText text, TextRange range, String newContent) throws IncorrectOperationException {
-
- final StringBuilder replacement = new StringBuilder(text.getValue());
- replacement.replace(
- range.getStartOffset(),
- range.getEndOffset(),
- newContent
- );
- text.setValue(replacement.toString());
+ final String newValue;
+ final String value = text.getValue();
+ if (range.equals(getRangeInElement(text))) {
+ newValue = newContent;
+ }
+ else {
+ final StringBuilder replacement = new StringBuilder(value);
+ replacement.replace(
+ range.getStartOffset(),
+ range.getEndOffset(),
+ newContent
+ );
+ newValue = replacement.toString();
+ }
+ if (Comparing.equal(value, newValue)) return text;
+ if (newValue.length() > 0) {
+ text.setValue(newValue);
+ }
+ else {
+ text.deleteChildRange(text.getFirstChild(), text.getLastChild());
+ }
return text;
}