Merge remote branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2011-12-21 11:40:09 +01:00
49 changed files with 592 additions and 207 deletions
@@ -55,13 +55,23 @@ import java.util.regex.PatternSyntaxException;
public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> implements HintAction, HighPriorityAction {
private final T myRef;
protected ImportClassFixBase(T ref) {
protected ImportClassFixBase(@NotNull T ref) {
myRef = ref;
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return myRef.isValid() && file.getManager().isInProject(file) && !getClassesToImport().isEmpty();
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) {
if (!myRef.isValid()) {
return false;
}
PsiManager manager = file.getManager();
if (!manager.isInProject(file)) {
return false;
}
if (getClassesToImport().isEmpty()) {
return false;
}
return true;
}
@Nullable
@@ -70,6 +80,7 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
protected abstract boolean hasTypeParameters(T reference);
@NotNull
public List<PsiClass> getClassesToImport() {
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(myRef.getProject());
String name = getReferenceName(myRef);
@@ -132,11 +132,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
}
if (isStringLiteral(token)) {
boolean escapeSlashes = true;
if (rawText != null && rawText.rawText != null) {
//is is assumed that all slashes are escaped in the raw text but some unescaped symbols can present (for example " copied from CharLiteral '"')
//so we should escape all needed symbols except slash.
escapeSlashes = false;
text = rawText.rawText;
}
@@ -144,7 +140,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
@NonNls String breaker = getLineBreaker(token);
final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true);
for (int i = 0; i < lines.length; i++) {
buffer.append(escapeCharCharacters(lines[i], token, escapeSlashes));
buffer.append(escapeCharCharacters(lines[i], token));
if (i != lines.length - 1 || "\n".equals(breaker) && text.endsWith("\n")) {
buffer.append(breaker);
}
@@ -153,10 +149,10 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
}
else if (isCharLiteral(token)) {
if (rawText != null && rawText.rawText != null) {
return escapeCharCharacters(rawText.rawText, token, false);
return escapeCharCharacters(rawText.rawText, token);
}
else {
return escapeCharCharacters(text, token, true);
return escapeCharCharacters(text, token);
}
}
return text;
@@ -206,9 +202,9 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
}
@NotNull
protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token, boolean escapeSlashes) {
protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token) {
StringBuilder buffer = new StringBuilder();
StringUtil.escapeStringCharacters(s.length(), s, isStringLiteral(token) ? "\"" : "\'",escapeSlashes, buffer);
StringUtil.escapeStringCharacters(s.length(), s, isStringLiteral(token) ? "\"" : "\'", buffer);
return buffer.toString();
}
}
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.search.GlobalSearchScope;
@@ -114,8 +115,9 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
}
for (final PsiReference ref : ReferencesSearch.search(myTargetParameter, new LocalSearchScope(myMethod), false)) {
if (ref.getElement() instanceof PsiReferenceExpression) {
result.add(new ParameterUsageInfo((PsiReferenceExpression)ref));
final PsiElement element = ref.getElement();
if (element instanceof PsiReferenceExpression || element instanceof PsiDocParamRef) {
result.add(new ParameterUsageInfo(ref));
}
}
@@ -344,15 +346,23 @@ public class ConvertToInstanceMethodProcessor extends BaseRefactoringProcessor {
}
private void processParameterUsage(ParameterUsageInfo usage) throws IncorrectOperationException {
final PsiJavaCodeReferenceElement referenceExpression = usage.getReferenceExpression();
if (referenceExpression.getParent() instanceof PsiReferenceExpression) {
// todo: check for correctness
referenceExpression.delete();
}
else {
final PsiExpression expression =
JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory().createExpressionFromText("this", null);
referenceExpression.replace(expression);
final PsiReference reference = usage.getReferenceExpression();
if (reference instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)reference;
if (referenceExpression.getParent() instanceof PsiReferenceExpression) {
// todo: check for correctness
referenceExpression.delete();
}
else {
final PsiExpression expression =
JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory().createExpressionFromText("this", null);
referenceExpression.replace(expression);
}
} else {
final PsiElement element = reference.getElement();
if (element instanceof PsiDocParamRef) {
element.getParent().delete();
}
}
}
@@ -15,22 +15,21 @@
*/
package com.intellij.refactoring.convertToInstanceMethod;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.PsiReference;
import com.intellij.usageView.UsageInfo;
/**
* @author dsl
*/
class ParameterUsageInfo extends UsageInfo {
private final PsiReferenceExpression myReferenceExpression;
private final PsiReference myReferenceExpression;
public ParameterUsageInfo(PsiReferenceExpression refereneceElement) {
super(refereneceElement);
myReferenceExpression = refereneceElement;
public ParameterUsageInfo(PsiReference referenceElement) {
super(referenceElement);
myReferenceExpression = referenceElement;
}
public PsiJavaCodeReferenceElement getReferenceExpression() {
public PsiReference getReferenceExpression() {
return myReferenceExpression;
}
}
@@ -38,8 +38,8 @@ import com.intellij.refactoring.MoveDestination;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.MoveCallback;
import com.intellij.refactoring.move.MoveHandler;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -170,6 +170,13 @@ public class MoveClassesOrPackagesToNewDirectoryDialog extends DialogWrapper {
return;
}
try {
MoveFilesOrDirectoriesUtil.checkIfMoveIntoSelf(myDirectory, directory);
}
catch (IncorrectOperationException e) {
Messages.showErrorDialog(project, e.getMessage(), RefactoringBundle.message("cannot.move"));
return;
}
super.doOKAction();
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(directory);
@@ -299,7 +299,7 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
@Override
@NotNull
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope) {
List<PsiClass> list = null;
String packageName = psiPackage.getQualifiedName();
for (PsiDirectory dir : psiPackage.getDirectories(scope)) {
@@ -315,9 +315,18 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
}
}
}
return list == null ? PsiClass.EMPTY_ARRAY : list.toArray(new PsiClass[list.size()]);
}
if (list == null) {
return PsiClass.EMPTY_ARRAY;
}
ContainerUtil.quickSort(list, new Comparator<PsiClass>() {
@Override
public int compare(PsiClass o1, PsiClass o2) {
return scope.compare(o2.getContainingFile().getVirtualFile(), o1.getContainingFile().getVirtualFile());
}
});
return list.toArray(new PsiClass[list.size()]);
}
@Override
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
@@ -0,0 +1,10 @@
class Test {
/**
* method description
* @param a description
*/
public static void ma<caret>in(A a) {
}
}
class A {}
@@ -0,0 +1,10 @@
class Test {
}
class A {
/**
* method description
*/
public void main() {
}
}
@@ -30,6 +30,8 @@ public class ConvertToInstanceMethodTest extends LightRefactoringTestCase {
public void testInterfaceTypeParameter() throws Exception { doTest(0); }
public void testJavadocParameter() throws Exception { doTest(0); }
private void doTest(final int targetParameter) throws Exception {
final String filePath = "/refactoring/convertToInstanceMethod/" + getTestName(false) + ".java";
configureByFile(filePath);
@@ -358,9 +358,9 @@ public class FindUsagesManager implements JDOMExternalizable {
private static UsageSearcher createUsageSearcher(final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
final FindUsagesHandler handler,
final FindUsagesOptions options,
FindUsagesOptions _options,
final PsiFile scopeFile) {
final FindUsagesOptions options = _options.clone();
return new UsageSearcher() {
@Override
public void generate(@NotNull final Processor<Usage> processor) {
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
@@ -55,6 +56,7 @@ import java.util.Map;
public class DirectoryChooser extends DialogWrapper {
@NonNls private static final String FILTER_NON_EXISTING = "filter_non_existing";
private static final String DEFAULT_SELECTION = "last_directory_selection";
private final DirectoryChooserView myView;
private boolean myFilterExisting;
private PsiDirectory myDefaultSelection;
@@ -106,6 +108,13 @@ public class DirectoryChooser extends DialogWrapper {
if (myTabbedPaneWrapper.getSelectedIndex() == 1) {
setSelection(myChooseByNamePanel.getChosenElement());
}
final ItemWrapper item = myView.getSelectedItem();
if (item != null) {
final PsiDirectory directory = item.getDirectory();
if (directory != null) {
PropertiesComponent.getInstance(directory.getProject()).setValue(DEFAULT_SELECTION, directory.getVirtualFile().getPath());
}
}
super.doOKAction();
}
@@ -363,8 +372,11 @@ public class DirectoryChooser extends DialogWrapper {
if (myView.getItemsSize() > 0){
myView.clearItems();
}
if (defaultSelection == null && directories.length > 0) {
defaultSelection = directories[0];
if (defaultSelection == null) {
defaultSelection = getDefaultSelection(directories, project);
if (defaultSelection == null && directories.length > 0) {
defaultSelection = directories[0];
}
}
int selectionIndex = -1;
for(int i = 0; i < directories.length; i++){
@@ -437,6 +449,19 @@ public class DirectoryChooser extends DialogWrapper {
myView.getComponent().repaint();
}
@Nullable
private static PsiDirectory getDefaultSelection(PsiDirectory[] directories, Project project) {
final String defaultSelectionPath = PropertiesComponent.getInstance(project).getValue(DEFAULT_SELECTION);
if (defaultSelectionPath != null) {
final VirtualFile directoryByDefault = LocalFileSystem.getInstance().findFileByPath(defaultSelectionPath);
if (directoryByDefault != null) {
final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(directoryByDefault);
return directory != null && ArrayUtil.find(directories, directory) > -1 ? directory : null;
}
}
return null;
}
private static boolean isParent(PsiDirectory directory, PsiDirectory parentCandidate) {
while (directory != null) {
if (directory.equals(parentCandidate)) return true;
@@ -36,6 +36,7 @@ import com.intellij.usages.UsageInfoToUsageConverter;
import com.intellij.util.Consumer;
import javax.swing.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -87,6 +88,7 @@ public class DependenciesUsagesPanel extends UsagesPanel {
elementsToSearch = searchFor;
usages = FindDependencyUtil.findDependencies(myBuilders, searchIn, searchFor);
}
assert !new HashSet<PsiFile>(elementsToSearch).contains(null);
}
catch (ProcessCanceledException e) {
}
@@ -74,6 +74,10 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
}
public void actionPerformed(AnActionEvent e) {
install();
}
public void install() {
IdeaPluginDescriptor[] selection = getPluginTable().getSelectedObjects();
if (userConfirm(selection)) {
@@ -113,14 +117,14 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
}
catch (IOException e1) {
PluginManagerMain.LOG.error(e1);
IOExceptionDialog.showErrorDialog(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("error.plugin.download.failed"));
IOExceptionDialog
.showErrorDialog(IdeBundle.message("action.download.and.install.plugin"), IdeBundle.message("error.plugin.download.failed"));
}
getPluginTable().updateUI();
}
}
public PluginTable getPluginTable() {
return host.getPluginTable();
}
@@ -16,7 +16,10 @@
package com.intellij.ide.plugins;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAware;
@@ -30,6 +33,8 @@ import javax.swing.*;
import java.awt.*;
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.LinkedHashSet;
@@ -87,6 +92,19 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
return ScrollPaneFactory.createScrollPane(pluginTable);
}
@Override
protected void installTableActions(final PluginTable pluginTable) {
super.installTableActions(pluginTable);
pluginTable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() != 2) return;
if (pluginTable.columnAtPoint(e.getPoint()) < 0) return;
if (pluginTable.rowAtPoint(e.getPoint()) < 0) return;
new ActionInstallPlugin(AvailablePluginsManagerMain.this, installed).install();
}
});
}
@Override
public void reset() {
UiNotifyConnector.doWhenFirstShown(getPluginTable(), new Runnable() {
@@ -247,19 +247,26 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa
super.stop();
if (isDialogShowing()) {
if (myFocusTrackback != null) {
myFocusTrackback.setWillBeSheduledForRestore();
}
}
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
boolean wasShowing = myDialog != null && myDialog.getPanel() != null && myDialog.getPanel().isShowing();
boolean wasShowing = isDialogShowing();
if (myDialog != null) {
myDialog.hide();
}
if (wasShowing) {
myFocusTrackback.restoreFocus();
} else {
myFocusTrackback.consume();
if (myFocusTrackback != null) {
if (wasShowing) {
myFocusTrackback.restoreFocus();
} else {
myFocusTrackback.consume();
}
}
myStoppedAlready = true;
@@ -271,6 +278,10 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa
SwingUtilities.invokeLater(EmptyRunnable.INSTANCE); // Just to give blocking dispatching a chance to go out.
}
private boolean isDialogShowing() {
return myDialog != null && myDialog.getPanel() != null && myDialog.getPanel().isShowing();
}
public void cancel() {
super.cancel();
if (myDialog != null) {
@@ -42,7 +42,7 @@ class StatusPanel extends JPanel {
private boolean myLogMode;
private boolean myDirty;
private boolean myAfterClick;
private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
private Alarm myLogAlarm;
private final TextPanel myTextPanel = new TextPanel() {
@Override
protected String getTextForPreferredSize() {
@@ -103,6 +103,17 @@ class StatusPanel extends JPanel {
return null;
}
private Alarm getAlarm() {
if (myLogAlarm == null || myLogAlarm.isDisposed()) {
myLogAlarm = null; //Welcome screen
Project project = getActiveProject();
if (project != null) {
myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project);
}
}
return myLogAlarm;
}
public void setLogMessage(String text) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -117,26 +128,30 @@ class StatusPanel extends JPanel {
final Project project = getActiveProject();
final Pair<Notification, Long> statusMessage = EventLog.getStatusMessage(project);
myLogMode = logAllowed && StringUtil.isEmpty(nonLogText) && statusMessage != null;
myLogAlarm.cancelAllRequests();
final Alarm alarm = getAlarm();
if (myLogMode) {
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
new Runnable() {
@Override
public void run() {
assert statusMessage != null;
String text = EventLog.formatForLog(statusMessage.first).status;
if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) {
text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")";
if (alarm != null) {
alarm.cancelAllRequests();
if (myLogMode) {
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
new Runnable() {
@Override
public void run() {
assert statusMessage != null;
String text = EventLog.formatForLog(statusMessage.first).status;
if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) {
text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")";
}
setStatusText(text);
alarm.addRequest(this, 30000);
}
setStatusText(text);
myLogAlarm.addRequest(this, 30000);
}
}.run();
} else {
myTextPanel.setCursor(Cursor.getDefaultCursor());
myDirty = true;
setStatusText(nonLogText);
}.run();
} else {
myTextPanel.setCursor(Cursor.getDefaultCursor());
myDirty = true;
setStatusText(nonLogText);
}
}
return myLogMode;
}
@@ -155,15 +170,18 @@ class StatusPanel extends JPanel {
}
public void restoreLogIfNeeded() {
myLogAlarm.cancelAllRequests();
myLogAlarm.addRequest(new Runnable() {
@Override
public void run() {
if (StringUtil.isEmpty(myTextPanel.getText())) {
updateText(true, "");
Alarm alarm = getAlarm();
if (alarm != null) {
alarm.cancelAllRequests();
alarm.addRequest(new Runnable() {
@Override
public void run() {
if (StringUtil.isEmpty(myTextPanel.getText())) {
updateText(true, "");
}
}
}
}, 300);
}, 300);
}
}
public String getText() {
@@ -307,7 +307,12 @@ public class FocusTrackback {
if (mustBeLastInStack) {
for (int i = index + 1; i < stack.size(); i++) {
if (!stack.get(i).isConsumed()) {
if (!stack.get(i).isMustBeShown()) {
if ((stack.get(i).isSheduledForRestore() || stack.get(i).isWillBeSheduledForRestore()) && !stack.get(i).isConsumed()) {
toFocus = null;
break;
}
} else if (!stack.get(i).isConsumed()) {
toFocus = null;
break;
}
@@ -445,7 +445,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
try {
LightPlatformTestCase.checkEditorsReleased();
}
catch (AssertionError error) {
catch (Throwable error) {
result.add(error);
}
}
@@ -119,7 +119,7 @@ public abstract class XBreakpointType<B extends XBreakpoint<P>, P extends XBreak
}
/**
* @deprecated override {@link #getEditorsProvider(XBreakpoint)} instead
* @deprecated override {@link #getEditorsProvider(B, com.intellij.openapi.project.Project)} instead
*/
@Nullable
public XDebuggerEditorsProvider getEditorsProvider() {
@@ -127,7 +127,7 @@ public abstract class XBreakpointType<B extends XBreakpoint<P>, P extends XBreak
}
@Nullable
public XDebuggerEditorsProvider getEditorsProvider(@NotNull B breakpoint) {
public XDebuggerEditorsProvider getEditorsProvider(@NotNull B breakpoint, @NotNull Project project) {
return getEditorsProvider();
}
@@ -63,7 +63,7 @@ public class XBreakpointPropertiesPanel<B extends XBreakpoint<?>> {
mySuspendPolicyPanel.init(project, breakpointManager, breakpoint);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint, project);
myBreakpointActionsPanel.init(project, breakpointManager, breakpoint, debuggerEditorsProvider);
@@ -105,7 +105,7 @@ public class XLightBreakpointPropertiesPanel<B extends XBreakpoint<?>> implement
mySubPanels.add(mySuspendPolicyPanel);
myMasterBreakpointPanel.init(project, breakpointManager, breakpoint);
mySubPanels.add(myMasterBreakpointPanel);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint);
XDebuggerEditorsProvider debuggerEditorsProvider = breakpointType.getEditorsProvider(breakpoint, project);
myActionsPanel.init(project, breakpointManager, breakpoint, debuggerEditorsProvider);
mySubPanels.add(myActionsPanel);
@@ -1,9 +1,25 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.testAssistant;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -22,14 +38,6 @@ import java.util.List;
*/
public class TestDataLineMarkerProvider implements LineMarkerProvider {
public LineMarkerInfo getLineMarkerInfo(PsiElement element) {
if (!(element instanceof PsiMethod)) {
return null;
}
final PsiMethod method = (PsiMethod)element;
if (isTestMethod(method)) {
return new LineMarkerInfo<PsiMethod>(method, method.getTextOffset(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null,
new TestDataNavigationHandler());
}
return null;
}
@@ -56,6 +64,20 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider {
}
public void collectSlowLineMarkers(List<PsiElement> elements, Collection<LineMarkerInfo> result) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
for (PsiElement element : elements) {
if (!(element instanceof PsiMethod)) {
continue;
}
final PsiMethod method = (PsiMethod)element;
if (isTestMethod(method)) {
result.add(new LineMarkerInfo<PsiMethod>(
method, method.getTextOffset(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null, new TestDataNavigationHandler()
));
}
}
}
@Nullable
@@ -69,13 +91,17 @@ public class TestDataLineMarkerProvider implements LineMarkerProvider {
final Object constantValue = evaluationHelper.computeConstantExpression(value, false);
if (constantValue instanceof String) {
String path = (String) constantValue;
if (path.indexOf("$CONTENT_ROOT") >= 0) {
if (path.contains("$CONTENT_ROOT")) {
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final VirtualFile contentRoot = fileIndex.getContentRootForFile(psiClass.getContainingFile().getVirtualFile());
final VirtualFile file = psiClass.getContainingFile().getVirtualFile();
if (file == null) {
return null;
}
final VirtualFile contentRoot = fileIndex.getContentRootForFile(file);
if (contentRoot == null) return null;
path = path.replace("$CONTENT_ROOT", contentRoot.getPath());
}
if (path.indexOf("$PROJECT_ROOT") >= 0) {
if (path.contains("$PROJECT_ROOT")) {
final VirtualFile baseDir = project.getBaseDir();
if (baseDir == null) {
return null;
+7 -2
View File
@@ -125,7 +125,7 @@ public class Git {
@NotNull
public static GitCommandResult clone(@NotNull Project project, @NotNull File parentDirectory, @NotNull String url, @NotNull String clonedDirectoryName) {
GitLineHandler handler = new GitLineHandler(project, parentDirectory, GitCommand.CLONE);
GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(project, parentDirectory, GitCommand.CLONE);
handler.addParameters(url);
handler.addParameters(clonedDirectoryName);
return run(handler, true);
@@ -221,7 +221,7 @@ public class Git {
}
public static GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec, @NotNull GitLineHandlerListener... listeners) {
final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.PUSH);
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(), GitCommand.PUSH);
h.setSilent(false);
for (GitLineHandlerListener listener : listeners) {
@@ -274,6 +274,11 @@ public class Git {
});
handler.runInCurrentThread(null);
if (handler instanceof GitLineHandlerPasswordRequestAware && ((GitLineHandlerPasswordRequestAware)handler).hadAuthRequest()) {
errorOutput.add("Authentication failed");
}
final boolean success = !startFailed.get() && errorOutput.isEmpty() && (handler.isIgnoredErrorCode(exitCode.get()) || exitCode.get() == 0);
return new GitCommandResult(success, exitCode.get(), errorOutput, output);
}
@@ -82,7 +82,7 @@ public class GitPull extends GitRepositoryAction {
return;
}
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(url)) {
if (GitHttpAdapter.shouldUseJGit(url)) {
boolean fetchSuccessful = new GitFetcher(project, indicator).fetchRootsAndNotify(gitRoots, "Push failed", false);
if (!fetchSuccessful) {
return;
@@ -104,7 +104,7 @@ public class GitCheckoutProvider implements CheckoutProvider {
}
private static boolean doClone(@NotNull Project project, @NotNull String directoryName, @NotNull String parentDirectory, @NotNull String sourceRepositoryURL) {
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(sourceRepositoryURL)) {
if (GitHttpAdapter.shouldUseJGit(sourceRepositoryURL)) {
GitFetchResult result = GitHttpAdapter.cloneRepository(project, new File(parentDirectory, directoryName), sourceRepositoryURL);
GitFetcher.displayFetchResult(project, result, "Clone failed", result.getErrors());
return result.isSuccess();
@@ -19,14 +19,15 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.EditorComboBox;
import com.intellij.util.ArrayUtil;
import git4idea.commands.*;
import git4idea.commands.GitCommand;
import git4idea.commands.GitLineHandlerPasswordRequestAware;
import git4idea.commands.GitTask;
import git4idea.commands.GitTaskResult;
import git4idea.i18n.GitBundle;
import git4idea.jgit.GitHttpAdapter;
import git4idea.remote.GitRememberedInputs;
import org.jetbrains.annotations.NonNls;
@@ -38,7 +39,6 @@ import java.awt.event.ActionListener;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
/**
@@ -141,7 +141,7 @@ public class GitCloneDialog extends DialogWrapper {
private void test() {
myTestURL = getCurrentUrlText();
boolean testResult = GitHttpAdapter.isHttpUrlWithoutUserCredentials(myTestURL) ? testHttp(myTestURL) : testNatively(myTestURL);
boolean testResult = test(myTestURL);
if (testResult) {
Messages.showInfoMessage(myTestButton, GitBundle.message("clone.test.success.message", myTestURL),
@@ -158,31 +158,13 @@ public class GitCloneDialog extends DialogWrapper {
* That way, we have a hack here: if http response asked for a password, then the url is at least valid and existant, and we consider
* that the test passed.
*/
private boolean testHttp(String url) {
final AtomicBoolean passwordRequested = new AtomicBoolean();
final GitLineHandler handler = new GitLineHandler(myProject, new File("."), GitCommand.LS_REMOTE);
handler.addParameters(url, "master");
handler.addLineListener(new GitLineHandlerAdapter() {
@Override
public void onLineAvailable(String line, Key outputType) {
String lowerCasedLine = line.toLowerCase();
if (lowerCasedLine.contains("password") || lowerCasedLine.contains("login") || lowerCasedLine.contains("username")) {
handler.cancel();
passwordRequested.set(true);
}
}
});
GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url));
GitTaskResult result = task.executeModal();
return result.isOK() || passwordRequested.get();
}
private boolean testNatively(String url) {
GitSimpleHandler handler = new GitSimpleHandler(myProject, new File("."), GitCommand.LS_REMOTE);
private boolean test(String url) {
final GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(myProject, new File("."), GitCommand.LS_REMOTE);
handler.addParameters(url, "master");
GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url));
GitTaskResult result = task.executeModal();
return result.isOK();
boolean authFailed = handler.hadAuthRequest();
return result.isOK() || authFailed;
}
/**
@@ -0,0 +1,55 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package git4idea.commands;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.io.File;
/**
* {@link GitLineHandler} that listens to Git output and kills itself if "username" or "password" is queried throughout the prompt.
* We can't pass the data to the prompt anyway, so better to kill the process and show an error message, than to hang the task.
*
* @author Kirill Likhodedov
*/
public class GitLineHandlerPasswordRequestAware extends GitLineHandler {
private boolean myAuthRequest;
public GitLineHandlerPasswordRequestAware(@NotNull Project project, @NotNull VirtualFile vcsRoot, @NotNull GitCommand command) {
super(project, vcsRoot, command);
}
public GitLineHandlerPasswordRequestAware(@NotNull Project project, @NotNull File directory, @NotNull GitCommand clone) {
super(project, directory, clone);
}
@Override
protected void onTextAvailable(String text, Key outputType) {
super.onTextAvailable(text, outputType);
if (text.toLowerCase().startsWith("password") || text.toLowerCase().startsWith("username")) {
myAuthRequest = true;
destroyProcess();
}
}
public boolean hadAuthRequest() {
return myAuthRequest;
}
}
@@ -65,11 +65,11 @@ public final class GitHttpAdapter {
private static final Pattern HTTP_URL_WITH_USERNAME_AND_PASSWORD = Pattern.compile("http(s?)://([^\\s^@:]+):([^\\s^@:]+)@.*");
public static boolean isHttpUrlWithoutUserCredentials(@NotNull String url) {
// if username & password are specified in the url, give it to the native Git
public static boolean shouldUseJGit(@NotNull String url) {
if (!url.startsWith("http")) {
return false;
}
// if username & password are specified in the url, give it to the native Git
if (HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches()) {
return false;
}
@@ -79,11 +79,11 @@ public final class GitHttpAdapter {
return !netrcData.hasAuthDataForUrl(url);
}
catch (FileNotFoundException e) {
return false;
return true;
}
catch (IOException e) {
LOG.warn("Couldn't read netrc file", e);
return false;
return true;
}
}
@@ -182,7 +182,7 @@ public class GitPullDialog extends DialogWrapper {
@NotNull
private Collection<String> getRemoteBranches(@NotNull GitDeprecatedRemote remote) {
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(remote.fetchUrl())) {
if (GitHttpAdapter.shouldUseJGit(remote.fetchUrl())) {
GitRepository repository = GitRepositoryManager.getInstance(myProject).getRepositoryForRoot(gitRoot());
if (repository == null) {
return Collections.emptyList();
@@ -332,7 +332,7 @@ public final class GitPusher {
return pushNatively(repository, pushSpec);
}
else {
return GitHttpAdapter.isHttpUrlWithoutUserCredentials(remoteUrl) ? GitHttpAdapter.push(repository, null, remoteUrl, null) : pushNatively(repository, pushSpec);
return GitHttpAdapter.shouldUseJGit(remoteUrl) ? GitHttpAdapter.push(repository, null, remoteUrl, null) : pushNatively(repository, pushSpec);
}
}
else {
@@ -340,7 +340,7 @@ public final class GitPusher {
assert remote != null : "Remote can't be null for pushSpec " + pushSpec;
String httpUrl = null;
for (String pushUrl : remote.getPushUrls()) {
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(pushUrl)) {
if (GitHttpAdapter.shouldUseJGit(pushUrl)) {
httpUrl = pushUrl;
break; // TODO support http and ssh urls in one origin
}
@@ -19,6 +19,7 @@ import com.intellij.notification.NotificationType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitVcs;
import git4idea.commands.*;
@@ -67,7 +68,7 @@ public class GitFetcher {
if (url == null) {
continue;
}
if (GitHttpAdapter.isHttpUrlWithoutUserCredentials(url)) {
if (GitHttpAdapter.shouldUseJGit(url)) {
GitFetchResult res = GitHttpAdapter.fetch(repository, remote, url);
myErrors.addAll(res.getErrors());
if (!res.isSuccess()) {
@@ -86,7 +87,7 @@ public class GitFetcher {
}
private boolean fetchNatively(@NotNull VirtualFile root, @NotNull GitRemote remote) {
final GitLineHandler h = new GitLineHandler(myProject, root, GitCommand.FETCH);
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(myProject, root, GitCommand.FETCH);
h.addParameters(remote.getName());
final GitTask fetchTask = new GitTask(myProject, h, "Fetching...");
fetchTask.setProgressIndicator(myProgressIndicator);
@@ -102,11 +103,15 @@ public class GitFetcher {
protected void onCancel() {
LOG.info("Cancelled fetch.");
}
@Override
protected void onFailure() {
LOG.info("Error fetching: " + h.errors());
myErrors.addAll(h.errors());
if (!h.hadAuthRequest()) {
myErrors.addAll(h.errors());
} else {
myErrors.add(new VcsException("Authentication failed"));
}
}
});
return success.get();
@@ -0,0 +1,3 @@
MACHine BITBUCKET.org
password pass
LOGIN john
@@ -0,0 +1 @@
n7 uppercase, login & password order change
@@ -0,0 +1 @@
bitbucket.org john pass
@@ -17,6 +17,7 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.AnnotatedScope
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClassScope
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClosureScope
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ScriptScope
import com.intellij.util.ObjectUtils
/**
* @author ilyas
@@ -24,7 +25,7 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ScriptScope
public class GroovyDslExecutor {
static final def cats = PsiEnhancerCategory.EP_NAME.extensions.collect { it.class }
final List<Pair<ContextFilter, Closure>> enhancers = []
final List<Pair<ContextFilter, Closure>> enhancers = ObjectUtils.assertNotNull([])
private final String myFileName;
static final String ideaVersion
@@ -17,14 +17,23 @@ package org.jetbrains.plugins.groovy.lang.editor;
import com.intellij.codeInsight.editorActions.StringLiteralCopyPasteProcessor;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RawText;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
@@ -106,51 +115,81 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce
}
@NotNull
@Override
protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token, boolean escapeSlashes) {
IElementType tokenType = token.getNode().getElementType();
public String preprocessOnPaste(Project project, PsiFile file, Editor editor, String text, RawText rawText) {
final Document document = editor.getDocument();
PsiDocumentManager.getInstance(project).commitDocument(document);
final SelectionModel selectionModel = editor.getSelectionModel();
if (tokenType == mREGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_CONTENT) {
if (escapeSlashes) {
return StringUtil.escapeSlashes(s);
}
else {
return s;
}
// pastes in block selection mode (column mode) are not handled by a CopyPasteProcessor
final int selectionStart = selectionModel.getSelectionStart();
final int selectionEnd = selectionModel.getSelectionEnd();
PsiElement token = findLiteralTokenType(file, selectionStart, selectionEnd);
if (token == null) {
return text;
}
String chars;
if (tokenType == mGSTRING_CONTENT || tokenType == mGSTRING_LITERAL) {
if (token.getText().contains("\"\"\"")) {
chars = "$";
}
else {
chars = "\"$";
if (isStringLiteral(token)) {
StringBuilder buffer = new StringBuilder(text.length());
@NonNls String breaker = getLineBreaker(token);
final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true);
for (int i = 0; i < lines.length; i++) {
buffer.append(escapeCharCharacters(lines[i], token));
if (i != lines.length - 1 || "\n".equals(breaker) && text.endsWith("\n")) {
buffer.append(breaker);
}
}
text = buffer.toString();
}
else if (tokenType == mSTRING_LITERAL && !token.getText().contains("'''")) {
chars = "'";
}
else {
chars = "";
}
StringBuilder buffer = new StringBuilder();
StringUtil.escapeStringCharacters(s.length(), s, chars, escapeSlashes, buffer);
return buffer.toString();
return text;
}
@NotNull
@Override
protected String unescape(String text, PsiElement token) {
final IElementType tokenType = token.getNode().getElementType();
protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token) {
IElementType tokenType = token.getNode().getElementType();
if (tokenType == mREGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_CONTENT) {
return StringUtil.unescapeSlashes(text);
if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) {
return GrStringUtil.escapeForSlashyStrings(s);
}
return super.unescape(text, token);
if (tokenType == mDOLLAR_SLASH_REGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_LITERAL) {
return GrStringUtil.escapeSymbolsForDollarSlashyStrings(s);
}
if (tokenType == mGSTRING_CONTENT || tokenType == mGSTRING_LITERAL) {
return GrStringUtil.escapeSymbolsForGString(s, !token.getText().contains("\"\"\""));
}
if (tokenType == mSTRING_LITERAL) {
return GrStringUtil.escapeSymbolsForString(s, !token.getText().contains("'''"));
}
return super.escapeCharCharacters(s, token);
}
@NotNull
@Override
protected String unescape(String s, PsiElement token) {
final IElementType tokenType = token.getNode().getElementType();
if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) {
return GrStringUtil.unescapeSlashyString(s);
}
if (tokenType == mDOLLAR_SLASH_REGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_LITERAL) {
return GrStringUtil.unescapeDollarSlashyString(s);
}
if (tokenType == mGSTRING_CONTENT || tokenType == mGSTRING_LITERAL) {
return StringUtil.unescapeStringCharacters(s);
}
if (tokenType == mSTRING_LITERAL) {
return StringUtil.unescapeStringCharacters(s);
}
return super.unescape(s, token);
}
}
@@ -34,6 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
@@ -45,6 +46,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrOpenBlockI
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterListImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.enumConstant.GrEnumConstantListImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrAnnotationMethodImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrConstructorImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrMethodImpl;
@@ -176,8 +178,12 @@ public interface GroovyElementTypes extends GroovyTokenTypes, GroovyDocElementTy
GroovyElementType BLOCK_STATEMENT = new GroovyElementType("Block statement");
// Enum
GroovyElementType ENUM_CONSTANTS = new GroovyElementType("Enumeration constants");
EmptyStubElementType<GrEnumConstantList> ENUM_CONSTANTS = new EmptyStubElementType<GrEnumConstantList>("Enumeration constants", GroovyFileType.GROOVY_LANGUAGE) {
@Override
public GrEnumConstantList createPsi(@NotNull EmptyStub stub) {
return new GrEnumConstantListImpl(stub);
}
};
GroovyElementType IMPORT_STATEMENT = new GroovyElementType("Import statement");
//Branch statements
GroovyElementType BREAK_STATEMENT = new GroovyElementType("Break statement");
@@ -374,7 +380,12 @@ public interface GroovyElementTypes extends GroovyTokenTypes, GroovyDocElementTy
}
};
IElementType ENUM_BODY = new GroovyElementType("enum block");
EmptyStubElementType<GrEnumDefinitionBody> ENUM_BODY = new EmptyStubElementType<GrEnumDefinitionBody>("enum block", GroovyFileType.GROOVY_LANGUAGE) {
@Override
public GrEnumDefinitionBody createPsi(@NotNull EmptyStub stub) {
return new GrTypeDefinitionBodyBase.GrEnumBody(stub);
}
};
//statements
GroovyElementType IF_STATEMENT = new GroovyElementType("if statement");
GroovyElementType FOR_STATEMENT = new GroovyElementType("for statement");
@@ -66,6 +66,7 @@ public class EnumConstant implements GroovyElementTypes {
PsiBuilder.Marker enumConstantsMarker = builder.mark();
if (!parseEnumConstant(builder, parser)) {
enumConstantsMarker.drop();
return;
}
@@ -15,11 +15,13 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList;
/**
* @author ven
*/
public interface GrEnumDefinitionBody extends GrTypeDefinitionBody {
@Nullable
GrEnumConstantList getEnumConstantList();
}
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members;
import com.intellij.psi.PsiEnumConstant;
import com.intellij.util.ArrayFactory;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
@@ -29,6 +30,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumConsta
*/
public interface GrEnumConstant extends GrField, GrConstructorCall, PsiEnumConstant {
GrEnumConstant[] EMPTY_ARRAY = new GrEnumConstant[0];
ArrayFactory<GrEnumConstant> ARRAY_FACTORY = new ArrayFactory<GrEnumConstant>() {
@Override
public GrEnumConstant[] create(int count) {
return new GrEnumConstant[count];
}
};
@Nullable
GrEnumConstantInitializer getInitializingClass();
@@ -66,7 +66,7 @@ public class GrEnumTypeDefinitionImpl extends GrTypeDefinitionImpl implements Gr
}
public GrEnumDefinitionBody getBody() {
return (GrEnumDefinitionBody)findChildByType(GroovyElementTypes.ENUM_BODY);
return getStubOrPsiChild(GroovyElementTypes.ENUM_BODY);
}
public boolean isEnum() {
@@ -173,13 +173,18 @@ public abstract class GrTypeDefinitionBodyBase extends GrStubElementBase<EmptySt
}
public static class GrEnumBody extends GrTypeDefinitionBodyBase implements GrEnumDefinitionBody {
public static class GrEnumBody extends GrTypeDefinitionBodyBase implements GrEnumDefinitionBody, StubBasedPsiElement<EmptyStub> {
public GrEnumBody(@NotNull ASTNode node) {
super(node);
}
public GrEnumBody(EmptyStub stub) {
super(stub, GroovyElementTypes.ENUM_BODY);
}
@Nullable
public GrEnumConstantList getEnumConstantList() {
return findChildByClass(GrEnumConstantList.class);
return getStubOrPsiChild(GroovyElementTypes.ENUM_CONSTANTS);
}
public void accept(GroovyElementVisitor visitor) {
@@ -17,21 +17,30 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.enumConstant;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.stubs.EmptyStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrStubElementBase;
/**
* @author: Dmitry.Krasilschikov
* @date: 06.04.2007
*/
public class GrEnumConstantListImpl extends GroovyPsiElementImpl implements GrEnumConstantList {
public class GrEnumConstantListImpl extends GrStubElementBase<EmptyStub> implements GrEnumConstantList, StubBasedPsiElement<EmptyStub> {
public GrEnumConstantListImpl(@NotNull ASTNode node) {
super(node);
}
public GrEnumConstantListImpl(EmptyStub stub) {
super(stub, GroovyElementTypes.ENUM_CONSTANTS);
}
public void accept(GroovyElementVisitor visitor) {
visitor.visitEnumConstants(this);
}
@@ -41,6 +50,11 @@ public class GrEnumConstantListImpl extends GroovyPsiElementImpl implements GrEn
}
public GrEnumConstant[] getEnumConstants() {
return findChildrenByClass(GrEnumConstant.class);
return getStubOrPsiChildren(GroovyElementTypes.ENUM_CONSTANT, GrEnumConstant.ARRAY_FACTORY);
}
@Override
public PsiElement getParent() {
return getParentByStub();
}
}
@@ -54,7 +54,7 @@ public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
@Override
public int getStubVersion() {
return super.getStubVersion() + 10;
return super.getStubVersion() + 11;
}
public String getExternalId() {
@@ -35,6 +35,67 @@ public class GrStringUtil {
private GrStringUtil() {
}
public static String unescapeSlashyString(String s) {
return unescapeRegex(s, true);
}
public static String unescapeDollarSlashyString(String s) {
return unescapeRegex(s, false);
}
private static String unescapeRegex(String s, boolean unescapeSlash) {
final int length = s.length();
StringBuilder buffer = new StringBuilder(length);
boolean escaped = false;
for (int idx = 0; idx < length; idx++) {
char ch = s.charAt(idx);
if (!escaped) {
if (ch == '\\') {
escaped = true;
}
else {
buffer.append(ch);
}
}
else {
switch (ch) {
case '/':
if (!unescapeSlash) {
buffer.append('\\');
}
buffer.append('/');
break;
case 'u':
if (idx + 4 < length) {
try {
int code = Integer.valueOf(s.substring(idx + 1, idx + 5), 16).intValue();
idx += 4;
buffer.append((char)code);
}
catch (NumberFormatException e) {
buffer.append("\\u");
}
}
else {
buffer.append("\\u");
}
break;
default:
buffer.append('\\');
buffer.append(ch);
break;
}
escaped = false;
}
}
if (escaped) buffer.append('\\');
return buffer.toString();
}
public static String escapeForSlashyStrings(String str) {
final StringBuilder buffer = new StringBuilder(str.length());
escapeSymbolsForSlashyStrings(buffer, str);
@@ -105,7 +166,7 @@ public class GrStringUtil {
public static String escapeSymbolsForGString(String s, boolean escapeDoubleQuotes, boolean forInjection) {
StringBuilder b = new StringBuilder();
escapeStringCharacters(s.length(), s, escapeDoubleQuotes ? "$\"" : "$", false, forInjection, b);
escapeStringCharacters(s.length(), s, escapeDoubleQuotes ? "$\"" : "$", forInjection, b);
if (!forInjection) {
unescapeCharacters(b, escapeDoubleQuotes ? "'" : "'\"", true);
}
@@ -118,7 +179,7 @@ public class GrStringUtil {
public static String escapeSymbolsForString(String s, boolean escapeQuotes, boolean forInjection) {
final StringBuilder builder = new StringBuilder();
escapeStringCharacters(s.length(), s, escapeQuotes ? "'" : "", false, forInjection, builder);
escapeStringCharacters(s.length(), s, escapeQuotes ? "'" : "", forInjection, builder);
if (!forInjection) {
unescapeCharacters(builder, escapeQuotes ? "$\"" : "$'\"", true);
}
@@ -129,8 +190,7 @@ public class GrStringUtil {
public static StringBuilder escapeStringCharacters(int length,
@NotNull String str,
@Nullable String additionalChars,
boolean escapeNR,
boolean escapeSlash,
boolean escapeLineFeeds,
@NotNull @NonNls StringBuilder buffer) {
for (int idx = 0; idx < length; idx++) {
char ch = str.charAt(idx);
@@ -148,16 +208,11 @@ public class GrStringUtil {
break;
case '\\':
if (escapeSlash) {
buffer.append("\\\\");
}
else {
buffer.append("\\");
}
buffer.append("\\\\");
break;
case '\n':
if (escapeNR) {
if (escapeLineFeeds) {
buffer.append("\\n");
}
else {
@@ -166,7 +221,7 @@ public class GrStringUtil {
break;
case '\r':
if (escapeNR) {
if (escapeLineFeeds) {
buffer.append("\\r");
}
else {
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2011 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.lang
import com.intellij.psi.impl.source.PsiFileImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiShortNamesCache
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumDefinitionBody
/**
* @author peter
*/
class GroovyStubsTest extends LightCodeInsightFixtureTestCase {
public void testEnumConstant() {
myFixture.tempDirFixture.createFile('A.groovy', 'enum A { MyEnumConstant }')
GrEnumConstant ec = (GrEnumConstant)PsiShortNamesCache.getInstance(project).getFieldsByName("MyEnumConstant", GlobalSearchScope.allScope(project))[0]
def file = (PsiFileImpl)ec.containingFile
assert file.stub
assert ec.containingClass.qualifiedName == 'A'
assert file.stub
assert ec in ec.containingClass.fields
assert ec in ((GrEnumDefinitionBody)((GrTypeDefinition)ec.containingClass).body).enumConstantList.enumConstants
assert file.stub
}
}
@@ -60,6 +60,6 @@ public class GroovyCopyClassTest extends LightCodeInsightFixtureTestCase {
def psiFile = myFixture.psiManager.findFile(file)
//would be copied as file
assertFalse(CopyClassesHandler.canCopyClass(myFixture.javaFacade.findClass("foo.$testName", GlobalSearchScope.allScope(project))));
assertFalse(CopyClassesHandler.canCopyClass(psiFile));
assertTrue(CopyClassesHandler.canCopyClass(psiFile));
}
}
@@ -33,13 +33,14 @@ import com.intellij.patterns.XmlPatterns;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlTokenType;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import com.intellij.xml.XmlBundle;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlExtension;
import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -142,19 +143,19 @@ public class XmlCompletionContributor extends CompletionContributor {
result.stopHere();
PsiElement parent = element.getParent();
if (!(parent instanceof XmlTag) ||
!(parameters.getOriginalFile() instanceof XmlFile) ||
!((XmlTag)parent).getNamespacePrefix().isEmpty()) {
!(parameters.getOriginalFile() instanceof XmlFile)) {
return;
}
final XmlTag tag = (XmlTag)parent;
final String namespace = tag.getNamespace();
final XmlElementDescriptor parentDescriptor = tag.getDescriptor();
final String prefix = result.getPrefixMatcher().getPrefix();
final int pos = prefix.indexOf(':');
final String namespacePrefix = pos > 0 ? prefix.substring(0, pos) : null;
final PsiReference reference = tag.getReference();
if (reference != null && namespace.length() > 0 && parentDescriptor != null && !(parentDescriptor instanceof AnyXmlElementDescriptor)) {
String namespacePrefix = tag.getNamespacePrefix();
if (reference != null && !namespace.isEmpty() && !namespacePrefix.isEmpty()) {
// fallback to simple completion
final Set<LookupElement> set = new HashSet<LookupElement>();
new XmlCompletionData().completeReference(reference, set, element, parameters.getOriginalFile(), parameters.getOffset());
for (final LookupElement item : set) {
@@ -170,7 +171,7 @@ public class XmlCompletionContributor extends CompletionContributor {
for (Pair<String, String> pair : names) {
final String name = pair.getFirst();
final String ns = pair.getSecond();
final LookupElement item = createLookupElement(name, ns, ns, namespacePrefix);
final LookupElement item = createLookupElement(name, ns, ns, namespacePrefix.isEmpty() ? null : namespacePrefix);
newResult.addElement(item);
}
}
@@ -60,8 +60,6 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
public static final XmlTagInsertHandler INSTANCE = new XmlTagInsertHandler();
public void handleInsert(InsertionContext context, LookupElement item) {
LOG.assertTrue(context.getTailOffset() >= 0);
Project project = context.getProject();
Editor editor = context.getEditor();
// Need to insert " " to prevent creating tags like <tagThis is my text
@@ -70,7 +68,6 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
PsiElement current = context.getFile().findElementAt(context.getStartOffset());
editor.getDocument().deleteString(offset, offset + 1);
LOG.assertTrue(context.getTailOffset() >= 0);
final XmlTag tag = PsiTreeUtil.getContextOfType(current, XmlTag.class, true);
@@ -87,7 +84,6 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
if (descriptor != null) {
insertIncompleteTag(context.getCompletionChar(), editor, project, descriptor, tag);
LOG.assertTrue(context.getTailOffset() >= 0);
}
}
else if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
@@ -112,8 +108,6 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
editor.getDocument().deleteString(sOffset, eOffset);
assert otherTag != null;
editor.getDocument().insertString(sOffset, ((XmlTag)otherTag).getName());
LOG.assertTrue(context.getTailOffset() >= 0);
}
}
@@ -122,15 +116,12 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
editor.getSelectionModel().removeSelection();
}
LOG.assertTrue(context.getTailOffset() >= 0);
if (context.getCompletionChar() == ' ' && TemplateManager.getInstance(project).getActiveTemplate(editor) != null) {
return;
}
final TailType tailType = LookupItem.handleCompletionChar(editor, item, context.getCompletionChar());
tailType.processTail(editor, editor.getCaretModel().getOffset());
LOG.assertTrue(context.getTailOffset() >= 0);
}
private static void insertIncompleteTag(char completionChar,