Merge remote branch 'origin/master'

This commit is contained in:
anna
2011-12-12 12:51:17 +01:00
44 changed files with 516 additions and 261 deletions
@@ -91,7 +91,7 @@ public class ConfigurationModuleSelector {
myModules.setSelectedItem(configuration.getConfigurationModule().getModule());
}
public static boolean isModuleAccepted(final Module module) {
public boolean isModuleAccepted(final Module module) {
return ModuleTypeManager.getInstance().isClasspathProvider(ModuleType.get(module));
}
@@ -19,6 +19,7 @@
*/
package com.intellij.ide.impl;
import com.intellij.ide.GeneralSettings;
import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
import com.intellij.ide.util.projectWizard.ProjectBuilder;
import com.intellij.openapi.application.ApplicationManager;
@@ -209,7 +210,7 @@ public class NewProjectUtil {
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
if (openProjects.length > 0) {
int exitCode = ProjectUtil.confirmOpenNewProject(true);
if (exitCode == 0) { // this window option
if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) {
ProjectUtil.closeAndDispose(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1]);
}
}
@@ -27,13 +27,17 @@ import com.intellij.openapi.util.NotNullLazyKey;
import com.intellij.psi.*;
import com.intellij.psi.impl.AnyPsiChangeListener;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import com.intellij.util.containers.WeakHashMap;
import com.intellij.util.containers.WeakList;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,6 +57,9 @@ public class JavaResolveCache {
private final ConcurrentMap<PsiExpression, PsiType> myCalculatedTypes = new ConcurrentWeakHashMap<PsiExpression, PsiType>();
private final ConcurrentMap<PsiElement, PsiType> myCachedReferencesInPsiTypes = new ConcurrentWeakHashMap<PsiElement, PsiType>();
// e.g. given FileOutputStream os, os2;
// PsiJavaCodeReferenceElement("FileOutputStream") -> [ PsiReferenceExpression("os"), PsiReferenceExpression("os2") ]
private final Map<PsiElement, WeakList<PsiElement>> myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere = new WeakHashMap<PsiElement, WeakList<PsiElement>>();
private final Map<PsiVariable,Object> myVarToConstValueMapPhysical;
private final Map<PsiVariable,Object> myVarToConstValueMapNonPhysical;
@@ -78,6 +85,7 @@ public class JavaResolveCache {
private void clearCaches(boolean isPhysical) {
myCalculatedTypes.clear();
myCachedReferencesInPsiTypes.clear();
myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.clear();
if (isPhysical) {
myVarToConstValueMapPhysical.clear();
}
@@ -96,8 +104,15 @@ public class JavaResolveCache {
if (type == null) {
type = TypeConversionUtil.NULL_TYPE;
}
type = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, expr, type);
PsiType stored = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, expr, type);
if (stored == type && DebugUtil.DO_EXPENSIVE_CHECKS) {
registerDiagnosticsHooks(expr, type);
}
type = stored;
}
if (!type.isValid()) {
if (expr.isValid()) {
PsiJavaCodeReferenceElement refInside = type instanceof PsiClassReferenceType ? ((PsiClassReferenceType)type).getReference() : null;
@@ -109,44 +124,86 @@ public class JavaResolveCache {
}
}
if (DebugUtil.DO_EXPENSIVE_CHECKS) {
if (type instanceof PsiClassReferenceType) {
PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType)type).getReference();
ConcurrencyUtil.cacheOrGet(myCachedReferencesInPsiTypes, reference, type);
DebugUtil.trackInvalidation(reference, "Reference inside PsiClassReferenceType was invalidated", new Processor<PsiElement>() {
@Override
public boolean process(PsiElement element) {
PsiType cached = myCalculatedTypes.get(element);
if (cached != null) {
LOG.error(element + " (inside ref) is invalid and yet it is still cached: " + cached);
}
PsiType cachedRef = myCachedReferencesInPsiTypes.get(element);
if (cachedRef != null) {
LOG.error(element + " (inside ref) is invalid and yet it is still cached in ref cache: " + cachedRef);
}
return true;
}
});
return type == TypeConversionUtil.NULL_TYPE ? null : type;
}
private <T extends PsiExpression> void registerDiagnosticsHooks(T expr, PsiType type) {
if (type instanceof PsiClassReferenceType) {
PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType)type).getReference();
ConcurrencyUtil.cacheOrGet(myCachedReferencesInPsiTypes, reference, type);
synchronized (myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere) {
WeakList<PsiElement> refsTo = myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.get(reference);
if (refsTo==null) {
refsTo = new WeakList<PsiElement>();
myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.put(reference, refsTo);
}
refsTo.add(expr);
}
DebugUtil.trackInvalidation(expr, "Expression invalidated", new Processor<PsiElement>() {
final PsiFile dummyHolder = reference.getContainingFile();
if (dummyHolder != null && !dummyHolder.isPhysical()) {
PsiElement physicalContext = dummyHolder.getContext();
PsiFile physicalFile;
if (physicalContext != null &&
(physicalFile = physicalContext.getContainingFile()) != null &&
physicalFile.getVirtualFile() != null &&
!((PsiManagerEx)PsiManager.getInstance(dummyHolder.getProject())).isAssertOnFileLoading(physicalFile.getVirtualFile())) {
DebugUtil.trackInvalidation(physicalContext, "dummy holder was invalidated", new Processor<PsiElement>() {
@Override
public boolean process(PsiElement element) {
DebugUtil.onInvalidated((TreeElement)dummyHolder.getNode());
return true;
}
});
}
}
DebugUtil.trackInvalidation(reference, "Reference inside PsiClassReferenceType was invalidated", new Processor<PsiElement>() {
@Override
public boolean process(PsiElement element) {
PsiType cached = myCalculatedTypes.get(element);
if (cached != null) {
LOG.error(element + " is invalid and yet it is still cached: " + cached);
LOG.error(element + " (inside ref) is invalid and yet it is still cached: " + cached);
}
PsiType cachedRef = myCachedReferencesInPsiTypes.get(element);
if (cachedRef != null) {
LOG.error(element + " is invalid and yet it is still cached (inside PsiType): " + cachedRef);
LOG.error(element + " (inside ref) is invalid and yet it is still cached in ref cache: " + cachedRef);
}
synchronized (myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere) {
WeakList<PsiElement> refsTo = myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.get(element);
if (refsTo != null) {
for (PsiElement ref : refsTo) {
PsiType cachedT = myCalculatedTypes.get(ref);
if (cachedT != null && !cachedT.isValid()) {
LOG.error("During invalidation of " + element + " ("+element.getClass()+")"+
" cached type " + cachedT + " of the ref "+ref+" ("+ref.getClass()+")"+
" became invalid and yet it is still cached"
);
}
}
}
}
return true;
}
});
}
DebugUtil.trackInvalidation(expr, "Expression invalidated", new Processor<PsiElement>() {
@Override
public boolean process(PsiElement element) {
PsiType cached = myCalculatedTypes.get(element);
if (cached != null) {
LOG.error(element + " is invalid and yet it is still cached: " + cached);
}
return type == TypeConversionUtil.NULL_TYPE ? null : type;
PsiType cachedRef = myCachedReferencesInPsiTypes.get(element);
if (cachedRef != null) {
LOG.error(element + " is invalid and yet it is still cached (inside PsiType): " + cachedRef);
}
return true;
}
});
}
@Nullable
@@ -490,7 +490,7 @@ public class DebugUtil {
}
public static void onInvalidated(@NotNull TreeElement treeElement) {
treeElement.acceptTree(new RecursiveTreeElementWalkingVisitor() {
treeElement.acceptTree(new RecursiveTreeElementWalkingVisitor(false) {
@Override
protected void visitNode(TreeElement element) {
List<Pair<Object, Processor<PsiElement>>> callbacks = element.getUserData(TRACK_INVALIDATION_KEY);
@@ -501,6 +501,7 @@ public class DebugUtil {
if (psi != null) callback.process(psi);
}
}
super.visitNode(element);
}
});
}
@@ -54,7 +54,7 @@ public class ExternalToolPassFactory extends AbstractProjectComponent implements
@Override
@Nullable
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) {
TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.EXTERNAL_TOOLS);
TextRange textRange = file.getTextRange();
if (textRange == null || !externalAnnotatorsDefined(file)) {
return null;
}
@@ -52,7 +52,7 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli
private String myLastProjectLocation;
private boolean mySearchInBackground;
private boolean myConfirmExit = true;
private int myConfirmOpenNewProject = -1;
private int myConfirmOpenNewProject = OPEN_PROJECT_ASK;
@NonNls private static final String ELEMENT_OPTION = "option";
@NonNls private static final String ATTRIBUTE_NAME = "name";
@NonNls private static final String ATTRIBUTE_VALUE = "value";
@@ -74,7 +74,7 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli
@NonNls private static final String OPTION_USE_CYCLIC_BUFFER = "useCyclicBuffer";
@NonNls private static final String OPTION_SEARCH_IN_BACKGROUND = "searchInBackground";
@NonNls private static final String OPTION_CONFIRM_EXIT = "confirmExit";
@NonNls private static final String OPTION_CONFIRM_OPEN_NEW_PROJECT = "confirmOpenNewProject";
@NonNls private static final String OPTION_CONFIRM_OPEN_NEW_PROJECT = "confirmOpenNewProject2";
@NonNls private static final String OPTION_CYCLIC_BUFFER_SIZE = "cyclicBufferSize";
@NonNls private static final String OPTION_LAST_PROJECT_LOCATION = "lastProjectLocation";
@Deprecated
@@ -331,7 +331,7 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli
myConfirmOpenNewProject = Integer.valueOf(value).intValue();
}
catch (Exception ex) {
myConfirmOpenNewProject = -1;
myConfirmOpenNewProject = OPEN_PROJECT_ASK;
}
}
@@ -477,9 +477,9 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli
/**
* @return
* <ul>
* <li>0 if new project should be opened in new window
* <li>1 if new project should be opened in same window
* <li>-1 if a confirmation dialog should be shown
* <li>{@link GeneralSettings#OPEN_PROJECT_NEW_WINDOW} if new project should be opened in new window
* <li>{@link GeneralSettings#OPEN_PROJECT_SAME_WINDOW} if new project should be opened in same window
* <li>{@link GeneralSettings#OPEN_PROJECT_ASK} if a confirmation dialog should be shown
* </ul>
*/
public int getConfirmOpenNewProject() {
@@ -184,6 +184,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
private static class MacClipboardHandler extends ClipboardHandler {
private static final String CLIPBOARD_CONTENTS = "CLIPBOARD_CONTENTS";
private static final String MAC_CLIPBOARD_SYNC_ACTIVE = "Mac.Clipboard.Sync.Active";
private Pair<String,Transferable> myFullTransferable;
private static Callback myClipboardQueryCallback = new Callback() {
@@ -195,7 +196,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
pane.putClientProperty(CLIPBOARD_CONTENTS, transferable);
}
pane.putClientProperty(MacUtil.MAC_NATIVE_WINDOW_SHOWING, null);
pane.putClientProperty(MAC_CLIPBOARD_SYNC_ACTIVE, null);
}
}
};
@@ -298,8 +299,8 @@ public class ClipboardSynchronizer implements ApplicationComponent {
.invoke(synchronizer, "performSelectorOnMainThread:withObject:waitUntilDone:", Foundation.createSelector("run:"), null,
false);
pane.putClientProperty(MacUtil.MAC_NATIVE_WINDOW_SHOWING, Boolean.TRUE);
MacUtil.startModal(pane);
pane.putClientProperty(MAC_CLIPBOARD_SYNC_ACTIVE, Boolean.TRUE);
MacUtil.startModal(pane, MAC_CLIPBOARD_SYNC_ACTIVE);
Foundation.cfRelease(synchronizer);
@@ -67,7 +67,7 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable<Searchabl
settings.setInactiveTimeout(newInactiveTimeout);
}
}
catch (NumberFormatException e) {
catch (NumberFormatException ignored) {
}
@@ -85,13 +85,14 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable<Searchabl
int openProjectOption = settings.getConfirmOpenNewProject();
isModified |= (myComponent.myConfirmFrameToOpenCheckBox.isSelected() && openProjectOption >= 0) || (!myComponent.myConfirmFrameToOpenCheckBox.isSelected() == openProjectOption < 0);
boolean savedOptionIsAsk = openProjectOption == GeneralSettings.OPEN_PROJECT_ASK;
isModified |= myComponent.myConfirmFrameToOpenCheckBox.isSelected() != savedOptionIsAsk;
int inactiveTimeout = -1;
try {
inactiveTimeout = Integer.parseInt(myComponent.myTfInactiveTimeout.getText());
}
catch (NumberFormatException e) {
catch (NumberFormatException ignored) {
}
isModified |= inactiveTimeout > 0 && settings.getInactiveTimeout() != inactiveTimeout;
@@ -141,7 +142,7 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable<Searchabl
myComponent.myTfInactiveTimeout.setText(Integer.toString(settings.getInactiveTimeout()));
myComponent.myTfInactiveTimeout.setEditable(settings.isAutoSaveIfInactive());
myComponent.myConfirmExit.setSelected(settings.isConfirmExit());
myComponent.myConfirmFrameToOpenCheckBox.setSelected(settings.getConfirmOpenNewProject() < 0);
myComponent.myConfirmFrameToOpenCheckBox.setSelected(settings.getConfirmOpenNewProject() == GeneralSettings.OPEN_PROJECT_ASK);
}
public void disposeUIResources() {
@@ -18,7 +18,6 @@ package com.intellij.ide.actions;
import com.intellij.ide.PasteProvider;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.SystemInfo;
public class PasteAction extends AnAction implements DumbAware {
@@ -27,7 +26,7 @@ public class PasteAction extends AnAction implements DumbAware {
DataContext dataContext = event.getDataContext();
PasteProvider provider = PlatformDataKeys.PASTE_PROVIDER.getData(dataContext);
presentation.setEnabled(provider != null && (SystemInfo.isMac || provider.isPastePossible(dataContext)));
presentation.setEnabled(provider != null && provider.isPastePossible(dataContext));
}
public void actionPerformed(AnActionEvent e) {
@@ -25,7 +25,9 @@ public class ProjectNewWindowDoNotAskOption implements DialogWrapper.DoNotAskOpt
}
public void setToBeShown(boolean value, int exitCode) {
GeneralSettings.getInstance().setConfirmOpenNewProject(value || exitCode == 2 ? -1 : exitCode);
int confirmOpenNewProject = value || exitCode == 2 ? GeneralSettings.OPEN_PROJECT_ASK :
exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : GeneralSettings.OPEN_PROJECT_NEW_WINDOW ;
GeneralSettings.getInstance().setConfirmOpenNewProject(confirmOpenNewProject);
}
public boolean canBeHidden() {
@@ -161,10 +161,10 @@ public class ProjectUtil {
if (!forceOpenInNewFrame && openProjects.length > 0) {
int exitCode = confirmOpenNewProject(false);
if (exitCode == 0) { // this window option
if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) {
if (!closeAndDispose(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1])) return null;
}
else if (exitCode != 1) { // not in a new window
else if (exitCode != GeneralSettings.OPEN_PROJECT_NEW_WINDOW) {
return null;
}
}
@@ -192,30 +192,33 @@ public class ProjectUtil {
}
/**
* @return 0 - this window
* 1 - new window
* 2 - cancel
* @return {@link com.intellij.ide.GeneralSettings#OPEN_PROJECT_SAME_WINDOW}
* {@link com.intellij.ide.GeneralSettings#OPEN_PROJECT_NEW_WINDOW}
* {@link com.intellij.openapi.ui.Messages#CANCEL} - if user canceled the dialog
* @param isNewProject
*/
public static int confirmOpenNewProject(boolean isNewProject) {
final GeneralSettings settings = GeneralSettings.getInstance();
if (settings.getConfirmOpenNewProject() == GeneralSettings.OPEN_PROJECT_ASK) {
int confirmOpenNewProject = settings.getConfirmOpenNewProject();
if (confirmOpenNewProject == GeneralSettings.OPEN_PROJECT_ASK) {
if (isNewProject) {
return Messages.showYesNoDialog(IdeBundle.message("prompt.open.project.in.new.frame"),
IdeBundle.message("title.new.project"),
IdeBundle.message("button.existingframe"),
IdeBundle.message("button.newframe"),
Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
int exitCode = Messages.showYesNoDialog(IdeBundle.message("prompt.open.project.in.new.frame"),
IdeBundle.message("title.new.project"),
IdeBundle.message("button.existingframe"),
IdeBundle.message("button.newframe"),
Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : GeneralSettings.OPEN_PROJECT_NEW_WINDOW;
}
else {
return Messages.showYesNoCancelDialog(IdeBundle.message("prompt.open.project.in.new.frame"),
IdeBundle.message("title.open.project"),
IdeBundle.message("button.existingframe"), IdeBundle.message("button.newframe"),
CommonBundle.getCancelButtonText(), Messages.getQuestionIcon(),
new ProjectNewWindowDoNotAskOption());
int exitCode = Messages.showYesNoCancelDialog(IdeBundle.message("prompt.open.project.in.new.frame"),
IdeBundle.message("title.open.project"),
IdeBundle.message("button.existingframe"), IdeBundle.message("button.newframe"),
CommonBundle.getCancelButtonText(), Messages.getQuestionIcon(),
new ProjectNewWindowDoNotAskOption());
return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : exitCode == 1 ? GeneralSettings.OPEN_PROJECT_NEW_WINDOW : Messages.CANCEL;
}
}
return settings.getConfirmOpenNewProject();
return confirmOpenNewProject;
}
private static boolean isSameProject(String path, Project p) {
@@ -154,7 +154,7 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme
@Nullable FileEditorProvider fallbackProvider,
final boolean changeEntryOrderOnly)
{
if (file == null){
if (file == null) {
return;
}
final FileEditorManagerEx editorManager = FileEditorManagerEx.getInstanceEx(myProject);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -230,7 +230,7 @@ class TextEditorComponent extends JPanel implements DataProvider{
* @return whether the editor is valid or not
*/
boolean isEditorValid(){
return myValid;
return myValid && !myEditor.isDisposed();
}
/**
@@ -16,6 +16,8 @@
package com.intellij.platform;
import com.intellij.conversion.ConversionResult;
import com.intellij.ide.GeneralSettings;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
@@ -125,10 +127,10 @@ public class PlatformProjectOpenProcessor extends ProjectOpenProcessor {
}
else {
int exitCode = ProjectUtil.confirmOpenNewProject(false);
if (exitCode == 0) { // this window option
if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) {
if (!ProjectUtil.closeAndDispose(projectToClose)) return null;
}
else if (exitCode != 1) { // not in a new window
else if (exitCode != GeneralSettings.OPEN_PROJECT_NEW_WINDOW) { // not in a new window
return null;
}
}
@@ -137,6 +137,13 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable {
if (window1 instanceof JFrame) {
ID w = MacUtil.findWindowForTitle(((JFrame)window1).getTitle());
if (w != null && w.intValue() > 0) {
try {
Thread.sleep(300);
}
catch (InterruptedException e1) {
// ignore
}
invoke(w, "setCollectionBehavior:", 1 << 7);
}
}
@@ -16,6 +16,7 @@
package com.intellij.usages;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -29,6 +30,7 @@ import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
@@ -96,7 +98,7 @@ public class ChunkExtractor {
};
public static TextChunk[] extractChunks(@NotNull PsiFile file, UsageInfo2UsageAdapter usageAdapter) {
return ourExtractors.get().getValue().get(file).extractChunks(usageAdapter);
return ourExtractors.get().getValue().get(file).extractChunks(usageAdapter, file);
}
@@ -124,7 +126,7 @@ public class ChunkExtractor {
return minStart == Integer.MAX_VALUE ? -1 : minStart;
}
private TextChunk[] extractChunks(UsageInfo2UsageAdapter usageInfo2UsageAdapter) {
private TextChunk[] extractChunks(@NotNull UsageInfo2UsageAdapter usageInfo2UsageAdapter, @NotNull PsiFile file) {
int absoluteStartOffset = usageInfo2UsageAdapter.getNavigationOffset();
if (absoluteStartOffset == -1) return TextChunk.EMPTY_ARRAY;
@@ -150,6 +152,14 @@ public class ChunkExtractor {
lineStartOffset = Math.max(lineStartOffset, absoluteStartOffset - OFFSET_BEFORE_TO_SHOW_WHEN_LONG_LINE);
lineEndOffset = Math.min(lineEndOffset, absoluteStartOffset + OFFSET_AFTER_TO_SHOW_WHEN_LONG_LINE);
}
if (myDocument instanceof DocumentWindow) {
List<TextRange> editable = InjectedLanguageManager.getInstance(file.getProject())
.intersectWithAllEditableFragments(file, new TextRange(lineStartOffset, lineEndOffset));
for (TextRange range : editable) {
createTextChunks(usageInfo2UsageAdapter, chars, range.getStartOffset(), range.getEndOffset(), result);
}
return result.toArray(new TextChunk[result.size()]);
}
return createTextChunks(usageInfo2UsageAdapter, chars, lineStartOffset, lineEndOffset, result);
}
@@ -18,6 +18,7 @@ package com.intellij.ui.mac.foundation;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import static com.intellij.ui.mac.foundation.Foundation.invoke;
@@ -67,12 +68,12 @@ public class MacUtil {
return focusedWindow;
}
public static synchronized void startModal(JComponent component) {
public static synchronized void startModal(JComponent component, String key) {
try {
if (SwingUtilities.isEventDispatchThread()) {
EventQueue theQueue = component.getToolkit().getSystemEventQueue();
while (component.getClientProperty(MAC_NATIVE_WINDOW_SHOWING) == Boolean.TRUE) {
while (component.getClientProperty(key) == Boolean.TRUE) {
AWTEvent event = theQueue.getNextEvent();
Object source = event.getSource();
if (event instanceof ActiveEvent) {
@@ -91,7 +92,7 @@ public class MacUtil {
}
else {
assert false: "Should be called from Event-Dispatch Thread only!";
while (component.getClientProperty(MAC_NATIVE_WINDOW_SHOWING) == Boolean.TRUE) {
while (component.getClientProperty(key) == Boolean.TRUE) {
// TODO:
//wait();
}
@@ -101,5 +102,9 @@ public class MacUtil {
}
}
public static synchronized void startModal(JComponent component) {
startModal(component, MAC_NATIVE_WINDOW_SHOWING);
}
}
@@ -307,6 +307,20 @@ public class AndroidModuleBuilder extends JavaModuleBuilder {
createChildDirectoryIfNotExist(project, contentRoot, SdkConstants.FD_ASSETS);
createChildDirectoryIfNotExist(project, contentRoot, SdkConstants.FD_NATIVE_LIBS);
}
else if (myProjectType == ProjectType.LIBRARY && myPackageName != null) {
final String[] dirs = myPackageName.split("\\.");
VirtualFile file = sourceRoot;
for (String dir : dirs) {
if (file == null || dir.length() == 0) {
break;
}
final VirtualFile childDir = file.findChild(dir);
file = childDir != null
? childDir
: file.createChildDirectory(project, dir);
}
}
}
catch (IOException e) {
LOG.error(e);
@@ -27,6 +27,7 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.ui.PanelWithAnchor;
import com.intellij.ui.RawCommandLineEditor;
import com.intellij.ui.components.JBLabel;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -73,7 +74,16 @@ public class AndroidRunConfigurationEditor<T extends AndroidRunConfigurationBase
myCommandLineField = myCommandLineComponent.getComponent();
myCommandLineField.setDialogCaption(myCommandLineComponent.getRawText());
myCommandLineComponent.getLabel().setLabelFor(myCommandLineField.getTextField());
myModuleSelector = new ConfigurationModuleSelector(project, myModulesComboBox);
myModuleSelector = new ConfigurationModuleSelector(project, myModulesComboBox) {
@Override
public boolean isModuleAccepted(Module module) {
if (module == null || !super.isModuleAccepted(module)) {
return false;
}
final AndroidFacet facet = AndroidFacet.getInstance(module);
return facet != null && !facet.getConfiguration().LIBRARY_PROJECT;
}
};
myAvdComboComponent.setComponent(new AvdComboBox(true, false) {
@Override
@@ -82,15 +82,19 @@ public class CvsRootConfiguration extends AbstractConfiguration implements CvsEn
}
private static String createFieldByFieldCvsRoot(CvsRepository cvsRepository) {
return createStringRepresentationOn(CvsMethod.getValue(cvsRepository.getMethod()), cvsRepository.getUser(), cvsRepository.getHost(),
String.valueOf(cvsRepository.getPort()), cvsRepository.getRepository());
}
public static String createStringRepresentationOn(CvsMethod method, String user, String host, String port, String repository) {
if (method == CvsMethod.LOCAL_METHOD) return repository;
if (method == CvsMethod.LOCAL_METHOD) {
final StringBuilder result = new StringBuilder();
result.append(SEPARATOR);
result.append(method.getName());
result.append(SEPARATOR);
result.append(repository);
return result.toString();
}
final StringBuilder result = new StringBuilder();
result.append(SEPARATOR);
result.append(method.getName());
@@ -143,11 +147,8 @@ public class CvsRootConfiguration extends AbstractConfiguration implements CvsEn
public void testConnection(Project project) throws AuthenticationException, IOException {
final IConnection connection = createSettings().createConnection(new ReadWriteStatistics());
final ErrorMessagesProcessor errorProcessor = new ErrorMessagesProcessor();
final CvsExecutionEnvironment cvsExecutionEnvironment = new CvsExecutionEnvironment(errorProcessor,
CvsExecutionEnvironment.DUMMY_STOPPER,
errorProcessor,
PostCvsActivity.DEAF,
project);
final CvsExecutionEnvironment cvsExecutionEnvironment =
new CvsExecutionEnvironment(errorProcessor, CvsExecutionEnvironment.DUMMY_STOPPER, errorProcessor, PostCvsActivity.DEAF, project);
final CvsResult result = new CvsResultEx();
try {
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@@ -93,7 +93,7 @@ public class GradleScriptType extends GroovyScriptType {
public void tuneConfiguration(@NotNull GroovyFile file, @NotNull GroovyScriptRunConfiguration configuration, Location location) {
String target = getTaskTarget(location);
if (target != null) {
configuration.setProgramParameters(target);
configuration.setScriptParameters(target);
configuration.setName(configuration.getName() + "." + target);
}
@@ -174,7 +174,9 @@ public class GradleScriptType extends GroovyScriptType {
public void configureCommandLine(JavaParameters params,
@Nullable Module module,
boolean tests,
VirtualFile script, GroovyScriptRunConfiguration configuration) throws CantRunException {
VirtualFile script, GroovyScriptRunConfiguration configuration)
throws CantRunException
{
final Project project = configuration.getProject();
final GradleLibraryManager libraryManager = ServiceManager.getService(GradleLibraryManager.class);
final VirtualFile gradleHome = libraryManager.getGradleHome(module, project);
@@ -208,10 +210,15 @@ public class GradleScriptType extends GroovyScriptType {
params.getVMParametersList().add("-Dgradle.home=" + FileUtil.toSystemDependentName(gradleHome.getPath()));
setToolsJar(params);
final String scriptPath = configuration.getScriptPath();
if (scriptPath == null) {
throw new CantRunException("Target script is undefined");
}
params.getProgramParametersList().add("--build-file");
params.getProgramParametersList().add(FileUtil.toSystemDependentName(configuration.getScriptPath()));
params.getProgramParametersList().add(FileUtil.toSystemDependentName(scriptPath));
params.getProgramParametersList().addParametersString(configuration.getProgramParameters());
params.getProgramParametersList().addParametersString(configuration.getScriptParameters());
}
};
}
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrRegex;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
import java.util.List;
@@ -39,30 +40,29 @@ public class GroovyLiteralSelectioner extends GroovyBasicSelectioner {
}
private static boolean isLiteral(PsiElement element) {
if (element instanceof GrListOrMap) {
return true;
}
if (element instanceof GrListOrMap) return true;
if (!(element instanceof GrLiteral)) return false;
if (element instanceof GrRegex && ((GrRegex)element).getInjections().length == 0) return true;
ASTNode node = element.getNode();
if (node == null) return false;
ASTNode firstNode = node.getFirstChildNode();
final IElementType type = firstNode.getElementType();
return firstNode == node.getLastChildNode() && (type == mSTRING_LITERAL || type == mGSTRING_LITERAL || type == mREGEX_LITERAL);
return firstNode == node.getLastChildNode() && (type == mSTRING_LITERAL || type == mGSTRING_LITERAL);
}
public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
List<TextRange> result = super.select(e, editorText, cursorOffset, editor);
if (e instanceof GrListOrMap) {
return result;
}
if (e instanceof GrListOrMap) return result;
int startOffset = -1;
int endOffset = -1;
final String text = e.getText();
final int stringOffset = e.getTextOffset();
if (e.getNode().getElementType() == mGSTRING_CONTENT) {
final IElementType elementType = e.getNode().getElementType();
if (elementType == mGSTRING_CONTENT || elementType == mREGEX_CONTENT || elementType == mDOLLAR_SLASH_REGEX_CONTENT) {
int cur;
int index = -1;
while (true) {
@@ -19,12 +19,13 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
/**
* @author Maxim.Medvedev
*/
@@ -46,7 +47,9 @@ public class GroovyWordSelectionFilter implements Condition<PsiElement> {
type == mREGEX_BEGIN ||
type == mREGEX_CONTENT ||
type == mREGEX_END ||
type == mWRONG_REGEX_LITERAL) {
type == mDOLLAR_SLASH_REGEX_BEGIN ||
type == mDOLLAR_SLASH_REGEX_CONTENT ||
type == mDOLLAR_SLASH_REGEX_END) {
return true;
}
@@ -49,8 +49,6 @@ public class DefaultHighlighter {
@NonNls
static final String STRING_ID = "String";
@NonNls
static final String REGEXP_ID = "Regular expression";
@NonNls
static final String BRACES_ID = "Braces";
@NonNls
static final String BRACKETS_ID = "Brackets";
@@ -150,9 +148,6 @@ public class DefaultHighlighter {
public static TextAttributesKey STRING = TextAttributesKey.createTextAttributesKey(STRING_ID,
SyntaxHighlighterColors.STRING.getDefaultAttributes());
public static TextAttributesKey REGEXP = TextAttributesKey.createTextAttributesKey(REGEXP_ID,
SyntaxHighlighterColors.VALID_STRING_ESCAPE.getDefaultAttributes());
public static TextAttributesKey BRACES = TextAttributesKey.createTextAttributesKey(BRACES_ID,
SyntaxHighlighterColors.BRACES.getDefaultAttributes());
@@ -19,14 +19,18 @@ package org.jetbrains.plugins.groovy.highlighter;
import com.intellij.lang.BracePair;
import com.intellij.lang.PairedBraceMatcher;
import com.intellij.psi.PsiFile;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import static com.intellij.psi.TokenType.WHITE_SPACE;
import static org.jetbrains.plugins.groovy.GroovyFileType.GROOVY_LANGUAGE;
import static org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes.mGDOC_INLINE_TAG_END;
import static org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes.mGDOC_INLINE_TAG_START;
import static org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes.mGDOC_TAG_VALUE_LPAREN;
import static org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes.mGDOC_TAG_VALUE_RPAREN;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.COMMENT_SET;
/**
* Brace matcher for Groovy language
@@ -36,32 +40,35 @@ import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
public class GroovyBraceMatcher implements PairedBraceMatcher {
private static final BracePair[] PAIRS = {
new BracePair(GroovyTokenTypes.mLPAREN, GroovyTokenTypes.mRPAREN, false),
new BracePair(GroovyTokenTypes.mLBRACK, GroovyTokenTypes.mRBRACK, false),
new BracePair(GroovyTokenTypes.mLCURLY, GroovyTokenTypes.mRCURLY, true),
new BracePair(mLPAREN, mRPAREN, false),
new BracePair(mLBRACK, mRBRACK, false),
new BracePair(mLCURLY, mRCURLY, true),
new BracePair(GroovyDocTokenTypes.mGDOC_INLINE_TAG_START, GroovyDocTokenTypes.mGDOC_INLINE_TAG_END, true),
new BracePair(GroovyDocTokenTypes.mGDOC_TAG_VALUE_LPAREN, GroovyDocTokenTypes.mGDOC_TAG_VALUE_RPAREN, false),
new BracePair(mGDOC_INLINE_TAG_START, mGDOC_INLINE_TAG_END, true),
new BracePair(mGDOC_TAG_VALUE_LPAREN, mGDOC_TAG_VALUE_RPAREN, false),
new BracePair(GroovyTokenTypes.mGSTRING_BEGIN, GroovyTokenTypes.mGSTRING_END, false),
new BracePair(GroovyTokenTypes.mREGEX_BEGIN, GroovyTokenTypes.mREGEX_END, false)
new BracePair(mGSTRING_BEGIN, mGSTRING_END, false),
new BracePair(mREGEX_BEGIN, mREGEX_END, false),
new BracePair(mDOLLAR_SLASH_REGEX_BEGIN, mDOLLAR_SLASH_REGEX_END, false),
};
public BracePair[] getPairs() {
return PAIRS;
}
public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType ibraceType, @Nullable IElementType tokenType) {
public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType braceType, @Nullable IElementType tokenType) {
return tokenType == null
|| TokenType.WHITE_SPACE == tokenType
|| TokenSets.COMMENT_SET.contains(tokenType)
|| tokenType == GroovyTokenTypes.mSEMI
|| tokenType == GroovyTokenTypes.mCOMMA
|| tokenType == GroovyTokenTypes.mRPAREN
|| tokenType == GroovyTokenTypes.mRBRACK
|| tokenType == GroovyTokenTypes.mRCURLY
|| tokenType == GroovyTokenTypes.mGSTRING_BEGIN
|| tokenType.getLanguage() != GroovyFileType.GROOVY_LANGUAGE;
|| tokenType == WHITE_SPACE
|| tokenType == mSEMI
|| tokenType == mCOMMA
|| tokenType == mRPAREN
|| tokenType == mRBRACK
|| tokenType == mRCURLY
|| tokenType == mGSTRING_BEGIN
|| tokenType == mREGEX_BEGIN
|| tokenType == mDOLLAR_SLASH_REGEX_BEGIN
|| COMMENT_SET.contains(tokenType)
|| tokenType.getLanguage() != GROOVY_LANGUAGE;
}
public int getCodeConstructStart(PsiFile file, int openingBraceOffset) {
@@ -58,7 +58,6 @@ public class GroovyColorsAndFontsPage implements ColorSettingsPage {
new AttributesDescriptor("Number", DefaultHighlighter.NUMBER),
new AttributesDescriptor("GString", DefaultHighlighter.GSTRING),
new AttributesDescriptor("String", DefaultHighlighter.STRING),
new AttributesDescriptor("Regular expression", DefaultHighlighter.REGEXP),
new AttributesDescriptor("Braces", DefaultHighlighter.BRACES),
new AttributesDescriptor("Brackets", DefaultHighlighter.BRACKETS),
new AttributesDescriptor("Parentheses", DefaultHighlighter.PARENTHESES),
@@ -0,0 +1,98 @@
/*
* 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.highlighter;
import com.intellij.lexer.LexerBase;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
/**
* @author Max Medvedev
*/
public class GroovySlashyStringLexer extends LexerBase {
private CharSequence myBuffer;
private int myStart;
private int myBufferEnd;
private IElementType myTokenType;
private int myEnd;
public GroovySlashyStringLexer() {
}
@Override
public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
myBuffer = buffer;
myEnd = startOffset;
myBufferEnd = endOffset;
myTokenType = locateToken();
}
@Nullable
private IElementType locateToken() {
if (myEnd >= myBufferEnd) return null;
myStart = myEnd;
if (checkForEscape(myStart)) {
myEnd = myStart + 2;
return StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN;
}
while (myEnd < myBufferEnd && !checkForEscape(myEnd)) myEnd++;
return GroovyTokenTypes.mREGEX_CONTENT;
}
private boolean checkForEscape(int start) {
return myBuffer.charAt(start) == '\\' && start + 1 < myBufferEnd && myBuffer.charAt(start + 1) == '/';
}
@Override
public int getState() {
return 0;
}
@Override
public IElementType getTokenType() {
return myTokenType;
}
@Override
public int getTokenStart() {
return myStart;
}
@Override
public int getTokenEnd() {
return myEnd;
}
@Override
public void advance() {
myTokenType = locateToken();
}
@Override
public CharSequence getBufferSequence() {
return myBuffer;
}
@Override
public int getBufferEnd() {
return myBufferEnd;
}
}
@@ -62,10 +62,6 @@ public class GroovySyntaxHighlighter extends SyntaxHighlighterBase implements Gr
mWRONG
);
static final TokenSet tWRONG_REGEX = TokenSet.create(
mWRONG_REGEX_LITERAL
);
static final TokenSet tGSTRINGS = TokenSet.create(
mGSTRING_BEGIN,
mGSTRING_CONTENT,
@@ -77,15 +73,6 @@ public class GroovySyntaxHighlighter extends SyntaxHighlighterBase implements Gr
mSTRING_LITERAL
);
static final TokenSet tREGEXP = TokenSet.create(
mREGEX_LITERAL,
mREGEX_BEGIN,
mREGEX_CONTENT,
mREGEX_END
);
static final TokenSet tBRACES = TokenSet.create(
mLCURLY,
mRCURLY
@@ -210,8 +197,7 @@ public class GroovySyntaxHighlighter extends SyntaxHighlighterBase implements Gr
fillMap(ATTRIBUTES, tNUMBERS, DefaultHighlighter.NUMBER);
fillMap(ATTRIBUTES, tGSTRINGS, DefaultHighlighter.GSTRING);
fillMap(ATTRIBUTES, tSTRINGS, DefaultHighlighter.STRING);
fillMap(ATTRIBUTES, tREGEXP, DefaultHighlighter.REGEXP);
fillMap(ATTRIBUTES, tWRONG_REGEX, DefaultHighlighter.REGEXP);
fillMap(ATTRIBUTES, DefaultHighlighter.STRING, mREGEX_BEGIN, mREGEX_CONTENT, mREGEX_END, mDOLLAR_SLASH_REGEX_BEGIN, mDOLLAR_SLASH_REGEX_CONTENT, mDOLLAR_SLASH_REGEX_END);
fillMap(ATTRIBUTES, tBRACES, DefaultHighlighter.BRACES);
fillMap(ATTRIBUTES, tBRACKETS, DefaultHighlighter.BRACKETS);
fillMap(ATTRIBUTES, tPARENTHESES, DefaultHighlighter.PARENTHESES);
@@ -234,6 +220,8 @@ public class GroovySyntaxHighlighter extends SyntaxHighlighterBase implements Gr
new IElementType[]{GroovyTokenTypes.mGSTRING_LITERAL}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new StringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, GroovyTokenTypes.mGSTRING_CONTENT, true, "$"),
new IElementType[]{GroovyTokenTypes.mGSTRING_CONTENT}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new GroovySlashyStringLexer(), new IElementType[]{GroovyTokenTypes.mREGEX_CONTENT},
IElementType.EMPTY_ARRAY);
}
}
@@ -111,10 +111,7 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce
protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token, boolean escapeSlashes) {
IElementType tokenType = token.getNode().getElementType();
if (tokenType == mREGEX_CONTENT ||
tokenType == mREGEX_LITERAL ||
tokenType == mDOLLAR_SLASH_REGEX_CONTENT ||
tokenType == mDOLLAR_SLASH_REGEX_LITERAL) {
if (tokenType == mREGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_CONTENT) {
if (escapeSlashes) {
return StringUtil.escapeSlashes(s);
}
@@ -149,10 +146,7 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce
protected String unescape(String text, PsiElement token) {
final IElementType tokenType = token.getNode().getElementType();
if (tokenType == mREGEX_CONTENT ||
tokenType == mREGEX_LITERAL ||
tokenType == mDOLLAR_SLASH_REGEX_CONTENT ||
tokenType == mDOLLAR_SLASH_REGEX_LITERAL) {
if (tokenType == mREGEX_CONTENT || tokenType == mDOLLAR_SLASH_REGEX_CONTENT) {
return StringUtil.unescapeSlashes(text);
}
@@ -73,10 +73,6 @@ public interface GroovyTokenTypes extends GroovyDocElementTypes {
IElementType mGSTRING_CONTENT = new GroovyElementType("Gstring content");
IElementType mGSTRING_END = new GroovyElementType("Gstring end");
IElementType mREGEX_LITERAL = new GroovyElementType("regexp");
IElementType mDOLLAR_SLASH_REGEX_LITERAL = new GroovyElementType("$/ regexp");
IElementType mWRONG_DOLLAR_SLASH_LITERAL = new GroovyElementType("wrong dollar slash literal");
IElementType mREGEX_BEGIN = new GroovyElementType("regex begin");
IElementType mREGEX_CONTENT = new GroovyElementType("regex content");
IElementType mREGEX_END = new GroovyElementType("regex end");
@@ -85,9 +81,6 @@ public interface GroovyTokenTypes extends GroovyDocElementTypes {
IElementType mDOLLAR_SLASH_REGEX_CONTENT = new GroovyElementType("$/ regex content");
IElementType mDOLLAR_SLASH_REGEX_END = new GroovyElementType("$/ regex end");
IElementType mWRONG_REGEX_LITERAL = new GroovyElementType("wrong regex");
IElementType mWRONG_DOLLAR_SLASH_REGEX_LITERAL = new GroovyElementType("wrong $/ regex");
/* **************************************************************************************************
* Common tokens: operators, braces etc.
* ****************************************************************************************************/
@@ -68,9 +68,7 @@ public abstract class TokenSets {
kFALSE,
kNULL,
mSTRING_LITERAL,
mGSTRING_LITERAL,
mREGEX_LITERAL,
mDOLLAR_SLASH_REGEX_LITERAL
mGSTRING_LITERAL
);
public static final TokenSet BUILT_IN_TYPE = TokenSet.create(
@@ -123,10 +121,8 @@ public abstract class TokenSets {
public static TokenSet STRING_LITERALS = TokenSet.create(
mSTRING_LITERAL,
mREGEX_LITERAL,
mREGEX_CONTENT,
mDOLLAR_SLASH_REGEX_CONTENT,
mDOLLAR_SLASH_REGEX_LITERAL,
mGSTRING_LITERAL,
mGSTRING_CONTENT,
mGSTRING_BEGIN,
@@ -115,11 +115,12 @@ public class ArgumentList implements GroovyElementTypes {
marker.done(ARGUMENT_LABEL);
return true;
}
else if (ParserUtils.lookAhead(builder, mIDENT, mCOLON) ||
TokenSets.KEYWORDS.contains(builder.getTokenType()) ||
mSTRING_LITERAL.equals(builder.getTokenType()) ||
mGSTRING_LITERAL.equals(builder.getTokenType()) ||
mREGEX_LITERAL.equals(builder.getTokenType())) {
final IElementType type = builder.getTokenType();
if (ParserUtils.lookAhead(builder, mIDENT, mCOLON) ||
TokenSets.KEYWORDS.contains(type) ||
mSTRING_LITERAL.equals(type) ||
mGSTRING_LITERAL.equals(type)) {
builder.advanceLexer();
if (mCOLON.equals(builder.getTokenType())) {
marker.done(ARGUMENT_LABEL);
@@ -130,12 +131,14 @@ public class ArgumentList implements GroovyElementTypes {
return false;
}
}
else if (mGSTRING_BEGIN.equals(builder.getTokenType()) ||
mREGEX_BEGIN.equals(builder.getTokenType()) ||
TokenSets.NUMBERS.contains(builder.getTokenType()) ||
mLBRACK.equals(builder.getTokenType()) ||
mLPAREN.equals(builder.getTokenType()) ||
mLCURLY.equals(builder.getTokenType())) {
if (mGSTRING_BEGIN.equals(type) ||
mREGEX_BEGIN.equals(type) ||
mDOLLAR_SLASH_REGEX_BEGIN.equals(type) ||
TokenSets.NUMBERS.contains(type) ||
mLBRACK.equals(type) ||
mLPAREN.equals(type) ||
mLCURLY.equals(type)) {
PrimaryExpression.parsePrimaryExpression(builder, parser);
if (mCOLON.equals(builder.getTokenType())) {
marker.done(ARGUMENT_LABEL);
@@ -146,11 +149,8 @@ public class ArgumentList implements GroovyElementTypes {
return false;
}
}
else {
marker.drop();
return false;
}
marker.drop();
return false;
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arguments.ArgumentList;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.DollarSlashRegexConstructorExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.PrimaryExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.RegexConstructorExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary.StringConstructorExpression;
@@ -227,17 +228,15 @@ public class PathExpression implements GroovyElementTypes {
}
final IElementType tokenType = builder.getTokenType();
if (mREGEX_LITERAL.equals(tokenType)) {
ParserUtils.eatElement(builder, REGEX);
return PATH_PROPERTY_REFERENCE;
}
if (mGSTRING_BEGIN.equals(tokenType)) {
StringConstructorExpression.parse(builder, parser);
return PATH_PROPERTY_REFERENCE;
}
if (mREGEX_BEGIN.equals(tokenType)) {
RegexConstructorExpression.parse(builder, parser);
return PATH_PROPERTY_REFERENCE;
return RegexConstructorExpression.parse(builder, parser) ? PATH_PROPERTY_REFERENCE : REFERENCE_EXPRESSION;
}
if (mDOLLAR_SLASH_REGEX_BEGIN.equals(tokenType)) {
return DollarSlashRegexConstructorExpression.parse(builder, parser) ? PATH_PROPERTY_REFERENCE : REFERENCE_EXPRESSION;
}
if (mLCURLY.equals(tokenType)) {
OpenOrClosableBlock.parseOpenBlock(builder, parser);
@@ -16,52 +16,40 @@
package org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary;
import com.intellij.lang.PsiBuilder;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyElementType;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arithmetic.PathExpression;
import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_BEGIN;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_CONTENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mDOLLAR_SLASH_REGEX_END;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mIDENT;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mLCURLY;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.*;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.GSTRING_INJECTION;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.REGEX;
/**
* @author Max Medvedev
*/
public class DollarSlashRegexConstructorExpression {
public static GroovyElementType parse(PsiBuilder builder, GroovyParser parser) {
private static final Logger LOG = Logger.getInstance(DollarSlashRegexConstructorExpression.class);
PsiBuilder.Marker sMarker = builder.mark();
if (ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_BEGIN)) {
public static boolean parse(PsiBuilder builder, GroovyParser parser) {
PsiBuilder.Marker marker = builder.mark();
final boolean result = ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_BEGIN);
LOG.assertTrue(result);
boolean inj = false;
ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_CONTENT);
while (parseInjection(builder, parser)) {
inj = true;
ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_CONTENT);
if (!parseInjection(builder, parser)) {
if (!ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_END)) {
builder.error(GroovyBundle.message("dollar.slash.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
else {
while (ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_CONTENT)) {
if (!parseInjection(builder, parser)) break;
}
if (!ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_END)) {
builder.error(GroovyBundle.message("dollar.slash.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
}
else {
sMarker.drop();
return WRONGWAY;
if (!ParserUtils.getToken(builder, mDOLLAR_SLASH_REGEX_END)) {
builder.error(GroovyBundle.message("dollar.slash.end.expected"));
}
marker.done(REGEX);
return inj;
}
/**
@@ -69,10 +69,12 @@ public class PrimaryExpression implements GroovyElementTypes {
return StringConstructorExpression.parse(builder, parser);
}
if (mREGEX_BEGIN == tokenType) {
return RegexConstructorExpression.parse(builder, parser);
RegexConstructorExpression.parse(builder, parser);
return REGEX;
}
if (mDOLLAR_SLASH_REGEX_BEGIN == tokenType) {
return DollarSlashRegexConstructorExpression.parse(builder, parser);
DollarSlashRegexConstructorExpression.parse(builder, parser);
return REGEX;
}
if (mLBRACK == tokenType) {
return ListOrMapConstructorExpression.parse(builder, parser);
@@ -83,31 +85,12 @@ public class PrimaryExpression implements GroovyElementTypes {
if (mLCURLY == tokenType) {
return OpenOrClosableBlock.parseClosableBlock(builder, parser);
}
if (tokenType == mSTRING_LITERAL ||
tokenType == mGSTRING_LITERAL ||
tokenType == mREGEX_LITERAL ||
tokenType == mDOLLAR_SLASH_REGEX_LITERAL) {
if (tokenType == mSTRING_LITERAL || tokenType == mGSTRING_LITERAL) {
return ParserUtils.eatElement(builder, literalsAsRefExprs ? REFERENCE_EXPRESSION : LITERAL);
}
if (TokenSets.CONSTANTS.contains(tokenType)) {
return ParserUtils.eatElement(builder, LITERAL);
}
if (mWRONG_REGEX_LITERAL == tokenType) {
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
builder.error(GroovyBundle.message("regex.end.expected"));
marker.done(LITERAL);
return LITERAL;
}
if (mWRONG_DOLLAR_SLASH_LITERAL == tokenType) {
final PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
builder.error(GroovyBundle.message("dollar.slash.end.expected"));
marker.done(LITERAL);
return LITERAL;
}
// TODO implement all cases!
return WRONGWAY;
}
@@ -17,8 +17,8 @@
package org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.primary;
import com.intellij.lang.PsiBuilder;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyElementType;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock;
@@ -29,34 +29,28 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
* @author ilyas
*/
public class RegexConstructorExpression implements GroovyElementTypes {
private static final Logger LOG = Logger.getInstance(RegexConstructorExpression.class);
public static GroovyElementType parse(PsiBuilder builder, GroovyParser parser) {
/**
* @return true if there are any injections
*/
public static boolean parse(PsiBuilder builder, GroovyParser parser) {
PsiBuilder.Marker marker = builder.mark();
final boolean result = ParserUtils.getToken(builder, mREGEX_BEGIN);
LOG.assertTrue(result);
PsiBuilder.Marker sMarker = builder.mark();
if (ParserUtils.getToken(builder, mREGEX_BEGIN)) {
boolean inj = false;
ParserUtils.getToken(builder, mREGEX_CONTENT);
while (parseInjection(builder, parser)) {
inj = true;
ParserUtils.getToken(builder, mREGEX_CONTENT);
if (!parseInjection(builder, parser)) {
if (!ParserUtils.getToken(builder, mREGEX_END)) {
builder.error(GroovyBundle.message("regex.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
else {
while (ParserUtils.getToken(builder, mREGEX_CONTENT)) {
if (!parseInjection(builder, parser)) break;
}
if (!ParserUtils.getToken(builder, mREGEX_END)) {
builder.error(GroovyBundle.message("regex.end.expected"));
}
sMarker.done(REGEX);
return REGEX;
}
}
else {
sMarker.drop();
return WRONGWAY;
if (!ParserUtils.getToken(builder, mREGEX_END)) {
builder.error(GroovyBundle.message("regex.end.expected"));
}
marker.done(REGEX);
return inj;
}
/**
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
@@ -30,6 +31,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrRefer
* @author ilyas
*/
public class GrPropertySelectionImpl extends GrReferenceExpressionImpl implements GrPropertySelection {
private static final Logger LOG = Logger.getInstance(GrPropertySelectionImpl.class);
public GrPropertySelectionImpl(@NotNull ASTNode node) {
super(node);
@@ -70,7 +72,7 @@ public class GrPropertySelectionImpl extends GrReferenceExpressionImpl implement
@Override
public PsiElement getReferenceNameElement() {
final PsiElement last = getLastChild();
assert last != null;
LOG.assertTrue(last!=null);
return last;
}
@@ -133,6 +133,7 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
public void testpath$path8() throws Throwable { doTest(); }
public void testpath$path9() throws Throwable { doTest(); }
public void testpath$path10() throws Throwable {doTest(); }
public void testpath$regexp() {doTest()}
public void testpath$typeVsExpr() {doTest();}
public void testreferences$ref1() throws Throwable { doTest(); }
public void testreferences$ref2() throws Throwable { doTest(); }
@@ -159,6 +160,8 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
public void testregex$regex2() throws Throwable { doTest(); }
public void testregex$regex20() throws Throwable { doTest(); }
public void testregex$regex21() throws Throwable { doTest(); }
public void testregex$regex22() throws Throwable { doTest(); }
public void testregex$regex23() throws Throwable { doTest(); }
public void testregex$regex3() throws Throwable { doTest(); }
public void testregex$regex33() throws Throwable { doTest(); }
public void testregex$regex4() throws Throwable { doTest(); }
@@ -0,0 +1,44 @@
a.$/dfg/$./fg/."sfg"./${a}/.$/df$g/$
-----
Groovy script
Property selection
Property selection
Reference expression
Reference expression
Reference expression
Reference expression
PsiElement(identifier)('a')
PsiElement(.)('.')
Compound regular expression
PsiElement($/ regex begin)('$/')
PsiElement($/ regex content)('dfg')
PsiElement($/ regex end)('/$')
PsiElement(.)('.')
Compound regular expression
PsiElement(regex begin)('/')
PsiElement(regex content)('fg')
PsiElement(regex end)('/')
PsiElement(.)('.')
PsiElement(Gstring)('"sfg"')
PsiElement(.)('.')
Compound regular expression
PsiElement(regex begin)('/')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Reference expression
PsiElement(identifier)('a')
PsiElement(})('}')
PsiElement(regex end)('/')
PsiElement(.)('.')
Compound regular expression
PsiElement($/ regex begin)('$/')
PsiElement($/ regex content)('df')
GString injection
PsiElement($)('$')
Reference expression
PsiElement(identifier)('g')
PsiElement($/ regex end)('/$')
@@ -36,7 +36,7 @@ Groovy script
Parameter list
<empty list>
Method call
Property selection
Reference expression
Reference expression
PsiElement(identifier)('frg')
PsiElement(.)('.')
@@ -0,0 +1,24 @@
/${1}${2}/
-----
Groovy script
Compound regular expression
PsiElement(regex begin)('/')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('1')
PsiElement(})('}')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('2')
PsiElement(})('}')
PsiElement(regex end)('/')
@@ -0,0 +1,24 @@
$/${1}${2}/$
-----
Groovy script
Compound regular expression
PsiElement($/ regex begin)('$/')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('1')
PsiElement(})('}')
GString injection
PsiElement($)('$')
Closable block
PsiElement({)('{')
Parameter list
<empty list>
Literal
PsiElement(Integer)('2')
PsiElement(})('}')
PsiElement($/ regex end)('/$')
@@ -52,7 +52,7 @@ Groovy script
Parameter list
<empty list>
Method call
Property selection
Reference expression
Reference expression
PsiElement(identifier)('frg')
PsiElement(.)('.')
@@ -53,7 +53,7 @@ Groovy script
Parameter list
<empty list>
Method call
Property selection
Reference expression
Reference expression
PsiElement(identifier)('frg')
PsiElement(.)('.')