mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote branch 'origin/master'
This commit is contained in:
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+3
-1
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+10
-9
@@ -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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+8
-8
@@ -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) {
|
||||
|
||||
+5
-2
@@ -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());
|
||||
|
||||
|
||||
+29
-22
@@ -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) {
|
||||
|
||||
-1
@@ -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),
|
||||
|
||||
+98
@@ -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;
|
||||
}
|
||||
}
|
||||
+3
-15
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-8
@@ -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,
|
||||
|
||||
+16
-16
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-6
@@ -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);
|
||||
|
||||
+19
-31
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-22
@@ -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;
|
||||
}
|
||||
|
||||
+18
-24
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -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(.)('.')
|
||||
|
||||
Reference in New Issue
Block a user