diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java index 298e1c663a34..197364969340 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java @@ -19,16 +19,29 @@ import com.intellij.extapi.psi.PsiFileBase; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.FileViewProvider; +import com.intellij.psi.util.PsiTreeUtil; +import org.intellij.lang.regexp.psi.RegExpGroup; import org.jetbrains.annotations.NotNull; +import java.util.Collection; + + public class RegExpFile extends PsiFileBase { - public RegExpFile(FileViewProvider viewProvider, final Language language) { - super(viewProvider, language); - } + public RegExpFile(FileViewProvider viewProvider, final Language language) { + super(viewProvider, language); + } - @NotNull - public FileType getFileType() { - return RegExpFileType.INSTANCE; - } + @NotNull + public FileType getFileType() { + return RegExpFileType.INSTANCE; + } + + /** + * @return Regexp groups this file has + */ + @NotNull + public Collection getGroups() { + return PsiTreeUtil.findChildrenOfType(this, RegExpGroup.class); + } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 27089fa70e91..fdc434d8d11a 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.source.tree.injected; +import com.intellij.extapi.psi.PsiFileBase; import com.intellij.injected.editor.*; import com.intellij.lang.Language; import com.intellij.lang.LanguageUtil; @@ -48,8 +49,10 @@ import java.util.List; * @author cdr */ public class InjectedLanguageUtil { - static final Key, TextRange>>> HIGHLIGHT_TOKENS = Key.create("HIGHLIGHT_TOKENS"); - public static Key FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); // meaning: injected file text is probably incorrect + static final Key, TextRange>>> HIGHLIGHT_TOKENS = + Key.create("HIGHLIGHT_TOKENS"); + public static Key FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); + // meaning: injected file text is probably incorrect public static void forceInjectionOnElement(@NotNull PsiElement host) { enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @@ -113,9 +116,9 @@ public class InjectedLanguageUtil { * @return true if enumerated successfully */ public static boolean enumerate(@NotNull PsiElement host, - @NotNull PsiFile containingFile, - boolean probeUp, - @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) { + @NotNull PsiFile containingFile, + boolean probeUp, + @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) { //do not inject into nonphysical files except during completion if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) { final PsiElement context = InjectedLanguageManager.getInstance(containingFile.getProject()).getInjectionHost(containingFile); @@ -175,6 +178,32 @@ public class InjectedLanguageUtil { return null; } + /** + * Finds injected language in expression + * + * @param expression where to find + * @param classToFind class that represents language we look for + * @param class that represents language we look for + * @return instance of class that represents language we look for or null of not found + */ + @Nullable + @SuppressWarnings("unchecked") // We check types dynamically (using isAssignableFrom) + public static T findInjectedFile(@NotNull final PsiElement expression, + @NotNull final Class classToFind) { + final List> files = + InjectedLanguageManager.getInstance(expression.getProject()).getInjectedPsiFiles(expression); + if (files == null) { + return null; + } + for (final Pair fileInfo : files) { + final PsiElement injectedFile = fileInfo.first; + if (classToFind.isAssignableFrom(injectedFile.getClass())) { + return (T)injectedFile; + } + } + return null; + } + public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable PsiFile file, final int offset) { if (editor == null || file == null || editor instanceof EditorWindow) return editor; PsiFile injectedFile = findInjectedPsiNoCommit(file, offset); @@ -200,7 +229,9 @@ public class InjectedLanguageUtil { } } } - if (!documentWindow.isValid()) return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied + if (!documentWindow.isValid()) { + return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied + } return EditorWindowImpl.create(documentWindow, (EditorImpl)hostEditor, injectedFile); } @@ -284,7 +315,8 @@ public class InjectedLanguageUtil { ParameterizedCachedValue cachedValue = CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false); - CachedValueProvider.Result result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar); + CachedValueProvider.Result result = + CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar); ((PsiParameterizedCachedValue)cachedValue).setValue(result); e.putUserData(INJECTED_PSI, cachedValue); @@ -307,7 +339,9 @@ public class InjectedLanguageUtil { // returns (injected psi, leaf element at the offset, language of the leaf element) // since findElementAt() is expensive, we trying to reuse its result @NotNull - private static Trinity tryOffset(@NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) { + private static Trinity tryOffset(@NotNull PsiFile hostFile, + final int offset, + @NotNull PsiDocumentManager documentManager) { FileViewProvider provider = hostFile.getViewProvider(); Language leafLanguage = null; PsiElement leafElement = null; @@ -319,11 +353,11 @@ public class InjectedLanguageUtil { leafElement = element; } PsiElement injected = findInside(element, hostFile, offset, documentManager); - if (injected != null) return Trinity.create(injected,element, language); + if (injected != null) return Trinity.create(injected, element, language); } // maybe we are at the border between two psi elements, then try to find injection at the end of the left element if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) { - PsiElement leftElement = provider.findElementAt(offset-1, language); + PsiElement leftElement = provider.findElementAt(offset - 1, language); if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) { PsiElement injected = findInside(leftElement, hostFile, offset, documentManager); if (injected != null) return Trinity.create(injected, element, language); @@ -334,7 +368,10 @@ public class InjectedLanguageUtil { return Trinity.create(null, leafElement, leafLanguage); } - private static PsiElement findInside(@NotNull PsiElement element, @NotNull PsiFile hostFile, final int hostOffset, @NotNull final PsiDocumentManager documentManager) { + private static PsiElement findInside(@NotNull PsiElement element, + @NotNull PsiFile hostFile, + final int hostOffset, + @NotNull final PsiDocumentManager documentManager) { final Ref out = new Ref(); enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override @@ -361,10 +398,12 @@ public class InjectedLanguageUtil { // modification of cachedInjectedDocuments must be under PsiLock only ConcurrentList injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY); if (injected == null) { - injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.createConcurrentList()); + injected = + ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.createConcurrentList()); } return injected; } + public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) { file.putUserData(INJECTED_DOCS_KEY, null); } @@ -426,10 +465,12 @@ public class InjectedLanguageUtil { } return containingFile; } + @NotNull public static Editor getTopLevelEditor(@NotNull Editor editor) { return editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor; } + public static boolean isInInjectedLanguagePrefixSuffix(@NotNull final PsiElement element) { PsiFile injectedFile = element.getContainingFile(); if (injectedFile == null) return false; @@ -461,13 +502,13 @@ public class InjectedLanguageUtil { public static String getUnescapedText(PsiFile file, @Nullable final PsiElement startElement, @Nullable final PsiElement endElement) { final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject()); if (manager.getInjectionHost(file) == null) { - return file.getText().substring(startElement == null? 0 : startElement.getTextRange().getStartOffset(), - endElement == null? file.getTextLength() : endElement.getTextRange().getStartOffset()); + return file.getText().substring(startElement == null ? 0 : startElement.getTextRange().getStartOffset(), + endElement == null ? file.getTextLength() : endElement.getTextRange().getStartOffset()); } final StringBuilder sb = new StringBuilder(); file.accept(new PsiRecursiveElementWalkingVisitor() { - Boolean myState = startElement == null? Boolean.TRUE : null; + Boolean myState = startElement == null ? Boolean.TRUE : null; @Override public void visitElement(PsiElement element) { diff --git a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java index fa8881062ac3..808ec477e89a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java +++ b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java @@ -25,6 +25,15 @@ import java.util.List; * @author vlan */ public interface StructuredDocString { + /** + * Creates parameter type documentation specific for certain doct type + * @param name param name + * @param type param type + * @return text to add to docsting + */ + @NotNull + String createParameterType(@NotNull String name, @NotNull String type); + String getDescription(); String getSummary(); diff --git a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java index 98f10f7abde1..36b70ec0f76a 100644 --- a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java +++ b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java @@ -76,12 +76,7 @@ public abstract class StructuredDocStringBase implements StructuredDocString { myDescription = builder.toString(); } - /** - * Creates parameter type documentation specific for certain doct type - * @param name param name - * @param type param type - * @return text to add to docsting - */ + @Override @NotNull public String createParameterType(@NotNull final String name, @NotNull final String type) { return myTagPrefix + TYPE + String.format(" %s %s", name, type); diff --git a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java index 4584f06ae8d9..6c86e72b1bcd 100644 --- a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java +++ b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java @@ -78,12 +78,12 @@ public abstract class PyInspectionVisitor extends PyElementVisitor { protected final void registerProblem(@Nullable final PsiElement element, @NotNull final String message, - @NotNull final LocalQuickFix quickFix) { + @NotNull final LocalQuickFix... quickFixes) { if (element == null || element.getTextLength() == 0) { return; } if (myHolder != null) { - myHolder.registerProblem(element, message, quickFix); + myHolder.registerProblem(element, message, quickFixes); } } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java index 0ae7ac1c7812..708e91743730 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java @@ -27,6 +27,7 @@ import com.jetbrains.python.psi.PyExpression; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +//TODO: Remove pydoc aswell public class PyRemoveArgumentQuickFix implements LocalQuickFix { @NotNull