public ProblemDescriptorImpl( @NotNull PsiElement startElement, @NotNull PsiElement endElement, String descriptionTemplate, LocalQuickFix[] fixes, ProblemHighlightType highlightType, boolean isAfterEndOfLine, @Nullable TextRange rangeInElement, final boolean tooltip, @Nullable HintAction hintAction, boolean onTheFly) { super(fixes, descriptionTemplate); myShowTooltip = tooltip; myHintAction = hintAction; PsiFile startContainingFile = startElement.getContainingFile(); LOG.assertTrue( startContainingFile != null && startContainingFile.isValid() || startElement.isValid(), startElement); PsiFile endContainingFile = startElement == endElement ? startContainingFile : endElement.getContainingFile(); LOG.assertTrue( startElement == endElement || endContainingFile != null && endContainingFile.isValid() || endElement.isValid(), endElement); assertPhysical(startElement); if (startElement != endElement) assertPhysical(endElement); final TextRange startElementRange = startElement.getTextRange(); LOG.assertTrue(startElementRange != null, startElement); final TextRange endElementRange = endElement.getTextRange(); LOG.assertTrue(endElementRange != null, endElement); if (startElementRange.getStartOffset() >= endElementRange.getEndOffset()) { if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) { LOG.error( "Empty PSI elements should not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement); } } myHighlightType = highlightType; final Project project = startContainingFile == null ? startElement.getProject() : startContainingFile.getProject(); final SmartPointerManager manager = SmartPointerManager.getInstance(project); myStartSmartPointer = manager.createSmartPsiElementPointer(startElement, startContainingFile); myEndSmartPointer = startElement == endElement ? null : manager.createSmartPsiElementPointer(endElement, endContainingFile); myAfterEndOfLine = isAfterEndOfLine; myTextRangeInElement = rangeInElement; }
@NotNull private List<AnnotationData> doCollect( @NotNull PsiModifierListOwner listOwner, boolean onlyWritable) { final List<PsiFile> files = findExternalAnnotationsFiles(listOwner); if (files == null) { return NO_DATA; } SmartList<AnnotationData> result = new SmartList<AnnotationData>(); String externalName = getExternalName(listOwner, false); if (externalName == null) return NO_DATA; for (PsiFile file : files) { if (!file.isValid()) continue; if (onlyWritable && !file.isWritable()) continue; MostlySingularMultiMap<String, AnnotationData> fileData = getDataFromFile(file); ContainerUtil.addAll(result, fileData.get(externalName)); } if (result.isEmpty()) { return NO_DATA; } result.trimToSize(); return result; }
/** * Retrieves indent options for PSI file from an associated document or (if not defined in the * document) from file indent options providers. * * @param file The PSI file to retrieve options for. * @param formatRange The text range within the file for formatting purposes or null if there is * either no specific range or multiple ranges. If the range covers the entire file (full * reformat), options stored in the document are ignored and indent options are taken from * file indent options providers. * @param ignoreDocOptions Ignore options stored in the document and use file indent options * providers even if there is no text range or the text range doesn't cover the entire file. * @param providerProcessor A callback object containing a reference to indent option provider * which has returned indent options. * @return Indent options from the associated document or file indent options providers. * @see com.intellij.psi.codeStyle.FileIndentOptionsProvider */ @NotNull public IndentOptions getIndentOptionsByFile( @Nullable PsiFile file, @Nullable TextRange formatRange, boolean ignoreDocOptions, @Nullable Processor<FileIndentOptionsProvider> providerProcessor) { if (file != null && file.isValid() && file.isWritable()) { boolean isFullReformat = isFileFullyCoveredByRange(file, formatRange); if (!ignoreDocOptions && !isFullReformat) { IndentOptions docOptions = IndentOptions.retrieveFromAssociatedDocument(file); if (docOptions != null) return docOptions; } FileIndentOptionsProvider[] providers = Extensions.getExtensions(FileIndentOptionsProvider.EP_NAME); for (FileIndentOptionsProvider provider : providers) { if (!isFullReformat || provider.useOnFullReformat()) { IndentOptions indentOptions = provider.getIndentOptions(this, file); if (indentOptions != null) { if (providerProcessor != null) { providerProcessor.process(provider); } logIndentOptions(file, provider, indentOptions); return indentOptions; } } } return getIndentOptions(file.getFileType()); } else return OTHER_INDENT_OPTIONS; }
public static Editor create( @NotNull final DocumentWindowImpl documentRange, @NotNull final EditorImpl editor, @NotNull final PsiFile injectedFile) { assert documentRange.isValid(); assert injectedFile.isValid(); EditorWindow window; synchronized (allEditors) { for (EditorWindow editorWindow : allEditors) { if (editorWindow.getDocument() == documentRange && editorWindow.getDelegate() == editor) { editorWindow.myInjectedFile = injectedFile; if (editorWindow.isValid()) { return editorWindow; } } if (editorWindow.getDocument().areRangesEqual(documentRange)) { // int i = 0; } } window = new EditorWindow(documentRange, editor, injectedFile, documentRange.isOneLine()); allEditors.add(window); } assert window.isValid(); return window; }
@Nullable private static VirtualFile findInitialDir(@NotNull final PsiFile psiFileRequestor) { if (!psiFileRequestor.isValid()) { return null; } return ApplicationManager.getApplication() .runReadAction( new Computable<VirtualFile>() { @Override @Nullable public VirtualFile compute() { Project project = psiFileRequestor.getProject(); VirtualFile virtualFile = psiFileRequestor.getVirtualFile(); if (virtualFile != null) { ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); VirtualFile contentRoot = fileIndex.getContentRootForFile(virtualFile); if (contentRoot != null) { return contentRoot; } } return project.getBaseDir(); } }); }
private void updateRightTreeModel() { Set<PsiFile> deps = new HashSet<PsiFile>(); Set<PsiFile> scope = getSelectedScope(myLeftTree); myIllegalsInRightTree = new HashSet<PsiFile>(); for (PsiFile psiFile : scope) { Map<DependencyRule, Set<PsiFile>> illegalDeps = myIllegalDependencies.get(psiFile); if (illegalDeps != null) { for (final DependencyRule rule : illegalDeps.keySet()) { myIllegalsInRightTree.addAll(illegalDeps.get(rule)); } } final Set<PsiFile> psiFiles = myDependencies.get(psiFile); if (psiFiles != null) { for (PsiFile file : psiFiles) { if (file != null && file.isValid()) { deps.add(file); } } } } deps.removeAll(scope); myRightTreeExpansionMonitor.freeze(); myRightTree.setModel(buildTreeModel(deps, myRightTreeMarker)); myRightTreeExpansionMonitor.restore(); expandFirstLevel(myRightTree); }
@NotNull public static <T extends PsiJavaCodeReferenceElement> JavaResolveResult[] multiResolveImpl( @NotNull T element, boolean incompleteCode, @NotNull ResolveCache.PolyVariantContextResolver<? super T> resolver) { FileASTNode fileElement = SharedImplUtil.findFileElement(element.getNode()); if (fileElement == null) { PsiUtilCore.ensureValid(element); LOG.error("fileElement == null!"); return JavaResolveResult.EMPTY_ARRAY; } PsiFile psiFile = SharedImplUtil.getContainingFile(fileElement); PsiManager manager = psiFile == null ? null : psiFile.getManager(); if (manager == null) { PsiUtilCore.ensureValid(element); LOG.error("getManager() == null!"); return JavaResolveResult.EMPTY_ARRAY; } boolean valid = psiFile.isValid(); if (!valid) { PsiUtilCore.ensureValid(element); LOG.error("psiFile.isValid() == false!"); return JavaResolveResult.EMPTY_ARRAY; } if (element instanceof PsiMethodReferenceExpression) { // method refs: do not cache results during parent conflict resolving, acceptable checks, etc final Map<PsiElement, PsiType> map = LambdaUtil.ourFunctionTypes.get(); if (map != null && map.containsKey(element)) { return (JavaResolveResult[]) resolver.resolve(element, psiFile, incompleteCode); } } return multiResolveImpl(manager.getProject(), psiFile, element, incompleteCode, resolver); }
public boolean isAvailable(PsiFile myFile) { return myFile != null && myFile.isValid() && myFile.getManager().isInProject(myFile) && myFile instanceof PsiJavaFile && ((PsiJavaFile) myFile).getClasses().length != 0 && myTargetPackage != null; }
@Override public boolean accept(PsiFile psiFile) { if (myFile == null || !myFile.equals(psiFile) || !myFile.isValid()) { return false; } return (myTodoFilter != null && myTodoFilter.accept(mySearchHelper, psiFile)) || (myTodoFilter == null && mySearchHelper.getTodoItemsCount(psiFile) > 0); }
private static boolean isCopyUpToDate(Document document, @NotNull PsiFile file) { if (!file.isValid()) { return false; } // the psi file cache might have been cleared by some external activity, // in which case PSI-document sync may stop working PsiFile current = PsiDocumentManager.getInstance(file.getProject()).getPsiFile(document); return current != null && current.getViewProvider().getPsi(file.getLanguage()) == file; }
// returns editor,file where the action is available or null if there are none public static boolean availableFor( @NotNull PsiFile file, @NotNull Editor editor, @NotNull IntentionAction action) { if (!file.isValid()) return false; int offset = editor.getCaretModel().getOffset(); PsiElement element = file.findElementAt(offset); boolean inProject = file.getManager().isInProject(file); return isAvailableHere(editor, file, element, inProject, action); }
@Override public void reparseRange(PsiFile file, int startOffset, int endOffset, CharSequence newTextS) throws IncorrectOperationException { LOG.assertTrue(file.isValid()); final PsiFileImpl psiFile = (PsiFileImpl) file; final Document document = psiFile.getViewProvider().getDocument(); assert document != null; document.replaceString(startOffset, endOffset, newTextS); PsiDocumentManager.getInstance(psiFile.getProject()).commitDocument(document); }
@Override public PsiElement restoreElement() { Segment segment = getPsiRange(); if (segment == null) return null; PsiFile file = restoreFile(); if (file == null || !file.isValid()) return null; return findElementInside(file, segment.getStartOffset(), segment.getEndOffset(), myType); }
@Override protected void validateCache() { super.validateCache(); if (myFile != null && !myFile.isValid()) { VirtualFile vFile = myFile.getVirtualFile(); if (vFile.isValid()) { myFile = PsiManager.getInstance(myProject).findFile(vFile); } else { myFile = null; } } }
@NotNull private static XmlFileHeader calcXmlFileHeader(final PsiFile file) { // if (file.getFileType() == XmlFileType.INSTANCE) { // VirtualFile virtualFile = file.getVirtualFile(); // if (virtualFile instanceof VirtualFileWithId) { // ObjectStubTree tree = StubTreeLoader.getInstance().readFromVFile(file.getProject(), // virtualFile); // if (tree != null) { // return ((FileStub)tree.getRoot()).getHeader(); // } // } // } if (file instanceof XmlFile && file.getNode().isParsed()) { final XmlDocument document = ((XmlFile) file).getDocument(); if (document != null) { String publicId = null; String systemId = null; final XmlProlog prolog = document.getProlog(); if (prolog != null) { final XmlDoctype doctype = prolog.getDoctype(); if (doctype != null) { publicId = doctype.getPublicId(); systemId = doctype.getSystemId(); if (systemId == null) { systemId = doctype.getDtdUri(); } } } final XmlTag tag = document.getRootTag(); if (tag != null) { String localName = tag.getLocalName(); if (StringUtil.isNotEmpty(localName)) { if (tag.getPrevSibling() instanceof PsiErrorElement) { return XmlFileHeader.EMPTY; } String psiNs = tag.getNamespace(); return new XmlFileHeader( localName, psiNs == XmlUtil.EMPTY_URI || Comparing.equal(psiNs, systemId) ? null : psiNs, publicId, systemId); } } } return XmlFileHeader.EMPTY; } if (!file.isValid()) return XmlFileHeader.EMPTY; return NanoXmlUtil.parseHeader(file); }
private boolean isValid() { if (isDumbMode() && !DumbService.isDumbAware(this)) { return false; } if (myDocument != null && myDocument.getModificationStamp() != myInitialStamp) return false; if (myProject != null && myDocument != null) { PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument); if (file == null || !file.isValid()) return false; } return true; }
public boolean isValid() { boolean valid = myNewVirtualFile.isValid() && (myAltFullRange == null && myInjectedFile.isValid() || myAltFullRange != null && myAltFullRange.isValid()); if (valid) { for (Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer> t : myMarkers) { if (!t.first.isValid() || !t.second.isValid() || t.third.getElement() == null) { valid = false; break; } } } return valid; }
@Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { if (file instanceof XmlFile && file.isValid() && AndroidFacet.getInstance(file) != null) { ResourceFolderType folderType = ResourceHelper.getFolderType(file); if (folderType == null) { return false; } else if (folderType != ResourceFolderType.VALUES) { return true; } else { return isAvailable(getValueTag(editor, file), file); } } return false; }
public GeneralHighlightingPass( @NotNull Project project, @NotNull PsiFile file, @NotNull Document document, int startOffset, int endOffset, boolean updateAll, @NotNull ProperTextRange priorityRange, @Nullable Editor editor) { super(project, document, PRESENTABLE_NAME, file, true); myStartOffset = startOffset; myEndOffset = endOffset; myUpdateAll = updateAll; myPriorityRange = priorityRange; myEditor = editor; LOG.assertTrue(file.isValid()); setId(Pass.UPDATE_ALL); myHasErrorElement = !isWholeFileHighlighting() && Boolean.TRUE.equals(myFile.getUserData(HAS_ERROR_ELEMENT)); FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(myProject)).getFileStatusMap(); myErrorFound = !isWholeFileHighlighting() && fileStatusMap.wasErrorFound(myDocument); myApplyCommand = new Runnable() { @Override public void run() { ProperTextRange range = new ProperTextRange(myStartOffset, myEndOffset); MarkupModel model = DocumentMarkupModel.forDocument(myDocument, myProject, true); UpdateHighlightersUtil.cleanFileLevelHighlights(myProject, Pass.UPDATE_ALL, myFile); final EditorColorsScheme colorsScheme = getColorsScheme(); UpdateHighlightersUtil.setHighlightersInRange( myProject, myDocument, range, colorsScheme, myHighlights, (MarkupModelEx) model, Pass.UPDATE_ALL); } }; // initial guess to show correct progress in the traffic light icon setProgressLimit(document.getTextLength() / 2); // approx number of PSI elements = file length/2 myGlobalScheme = EditorColorsManager.getInstance().getGlobalScheme(); }
// returns number of hits static int processUsagesInFile( @NotNull final PsiFile psiFile, @NotNull final FindModel findModel, @NotNull final Processor<UsageInfo> consumer) { if (findModel.getStringToFind().isEmpty()) { if (!ApplicationManager.getApplication() .runReadAction((Computable<Boolean>) () -> consumer.process(new UsageInfo(psiFile)))) { throw new ProcessCanceledException(); } return 1; } final VirtualFile virtualFile = psiFile.getVirtualFile(); if (virtualFile == null) return 0; if (virtualFile.getFileType().isBinary()) return 0; // do not decompile .class files final Document document = ApplicationManager.getApplication() .runReadAction( (Computable<Document>) () -> virtualFile.isValid() ? FileDocumentManager.getInstance().getDocument(virtualFile) : null); if (document == null) return 0; final int[] offset = {0}; int count = 0; int found; ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator()); TooManyUsagesStatus tooManyUsagesStatus = TooManyUsagesStatus.getFrom(indicator); do { tooManyUsagesStatus.pauseProcessingIfTooManyUsages(); // wait for user out of read action found = ApplicationManager.getApplication() .runReadAction( (Computable<Integer>) () -> { if (!psiFile.isValid()) return 0; return addToUsages( document, consumer, findModel, psiFile, offset, USAGES_PER_READ_ACTION); }); count += found; } while (found != 0); return count; }
public boolean isAvailable(@Nullable XmlTag tag, PsiFile file) { if (file instanceof XmlFile && file.isValid() && AndroidFacet.getInstance(file) != null) { ResourceFolderType folderType = ResourceHelper.getFolderType(file); if (folderType == null) { return false; } else if (folderType != ResourceFolderType.VALUES) { return true; } else { // In value files, you can invoke this action if the caret is on or inside an element (other // than the // root <resources> tag). Only accept the element if it has a known type with a known name. if (tag != null && tag.getAttributeValue(ATTR_NAME) != null) { return AndroidResourceUtil.getResourceForResourceTag(tag) != null; } } } return false; }
private void invokeCompletion(final ExpressionContext context) { final Project project = context.getProject(); final Editor editor = context.getEditor(); final PsiFile psiFile = editor != null ? PsiUtilBase.getPsiFileInEditor(editor, project) : null; Runnable runnable = () -> { if (project.isDisposed() || editor == null || editor.isDisposed() || psiFile == null || !psiFile.isValid()) return; // it's invokeLater, so another completion could have started if (CompletionServiceImpl.getCompletionService().getCurrentCompletion() != null) return; CommandProcessor.getInstance() .executeCommand( project, () -> { // if we're in some completion's insert handler, make sure our new completion // isn't treated as the second invocation CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion); invokeCompletionHandler(project, editor); Lookup lookup = LookupManager.getInstance(project).getActiveLookup(); if (lookup != null) { lookup.addLookupListener( new MyLookupListener(context, myCheckCompletionChar)); } }, "", null); }; ApplicationManager.getApplication().invokeLater(runnable); }
private static boolean activatePsiElementIfOpen( @NotNull PsiElement elt, boolean searchForOpen, boolean requestFocus) { if (!elt.isValid()) return false; elt = elt.getNavigationElement(); final PsiFile file = elt.getContainingFile(); if (file == null || !file.isValid()) return false; VirtualFile vFile = file.getVirtualFile(); if (vFile == null) return false; if (!EditorHistoryManager.getInstance(elt.getProject()).hasBeenOpen(vFile)) return false; final FileEditorManager fem = FileEditorManager.getInstance(elt.getProject()); if (!fem.isFileOpen(vFile)) { fem.openFile(vFile, requestFocus, searchForOpen); } final TextRange range = elt.getTextRange(); if (range == null) return false; final FileEditor[] editors = fem.getEditors(vFile); for (FileEditor editor : editors) { if (editor instanceof TextEditor) { final Editor text = ((TextEditor) editor).getEditor(); final int offset = text.getCaretModel().getOffset(); if (range.containsOffset(offset)) { // select the file fem.openFile(vFile, requestFocus, searchForOpen); return true; } } } return false; }
@NotNull private List<Pair<PsiClass, VirtualFile>> doFindClasses( @NotNull String qName, @NotNull final GlobalSearchScope scope) { final Collection<PsiClass> classes = JavaFullClassNameIndex.getInstance().get(qName.hashCode(), myManager.getProject(), scope); if (classes.isEmpty()) return Collections.emptyList(); List<Pair<PsiClass, VirtualFile>> result = new ArrayList<>(classes.size()); for (PsiClass aClass : classes) { final String qualifiedName = aClass.getQualifiedName(); if (qualifiedName == null || !qualifiedName.equals(qName)) continue; PsiFile file = aClass.getContainingFile(); if (file == null) { throw new AssertionError("No file for class: " + aClass + " of " + aClass.getClass()); } final boolean valid = file.isValid(); VirtualFile vFile = file.getVirtualFile(); if (!valid) { LOG.error( "Invalid file " + file + "; virtualFile:" + vFile + (vFile != null && !vFile.isValid() ? " (invalid)" : "") + "; id=" + (vFile == null ? 0 : ((VirtualFileWithId) vFile).getId()), new PsiInvalidElementAccessException(aClass)); continue; } if (!hasAcceptablePackage(vFile)) continue; result.add(Pair.create(aClass, vFile)); } return result; }
@Override public void startRunInjectors(@NotNull final Document hostDocument, final boolean synchronously) { if (myProject.isDisposed()) return; if (!synchronously && ApplicationManager.getApplication().isWriteAccessAllowed()) return; // use cached to avoid recreate PSI in alien project final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument); if (hostPsiFile == null) return; final ConcurrentList<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile); if (injected.isEmpty()) return; if (myProgress.isCanceled()) { myProgress = new DaemonProgressIndicator(); } final Set<DocumentWindow> newDocuments = Collections.synchronizedSet(new THashSet<>()); final Processor<DocumentWindow> commitProcessor = documentWindow -> { if (myProject.isDisposed()) return false; ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); if (indicator != null && indicator.isCanceled()) return false; if (documentManager.isUncommited(hostDocument) || !hostPsiFile.isValid()) return false; // will be committed later // it is here where the reparse happens and old file contents replaced InjectedLanguageUtil.enumerate( documentWindow, hostPsiFile, (injectedPsi, places) -> { DocumentWindow newDocument = (DocumentWindow) injectedPsi.getViewProvider().getDocument(); if (newDocument != null) { PsiDocumentManagerBase.checkConsistency(injectedPsi, newDocument); newDocuments.add(newDocument); } }); return true; }; final Runnable commitInjectionsRunnable = () -> { if (myProgress.isCanceled()) return; JobLauncher.getInstance() .invokeConcurrentlyUnderProgress( new ArrayList<>(injected), myProgress, true, commitProcessor); synchronized (ourInjectionPsiLock) { injected.clear(); injected.addAll(newDocuments); } }; if (synchronously) { if (Thread.holdsLock(PsiLock.LOCK)) { // hack for the case when docCommit was called from within PSI modification, e.g. in // formatter. // we can't spawn threads to do injections there, otherwise a deadlock is imminent ContainerUtil.process(new ArrayList<>(injected), commitProcessor); } else { commitInjectionsRunnable.run(); } } else { JobLauncher.getInstance() .submitToJobThread( () -> ApplicationManagerEx.getApplicationEx() .tryRunReadAction(commitInjectionsRunnable), null); } }
private boolean isValid() { return !isDisposed() && !myInjectedFile.getProject().isDisposed() && myInjectedFile.isValid() && myDocumentWindow.isValid(); }
@Override @Nullable public List<PsiFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) { final PsiFile containingFile = listOwner.getContainingFile(); if (!(containingFile instanceof PsiJavaFile)) { return null; } final PsiJavaFile javaFile = (PsiJavaFile) containingFile; final String packageName = javaFile.getPackageName(); final VirtualFile virtualFile = containingFile.getVirtualFile(); if (virtualFile == null) return null; final List<PsiFile> files = myExternalAnnotations.get(virtualFile); if (files == NULL_LIST) return null; if (files != null) { boolean allValid = true; for (PsiFile file : files) { allValid &= file.isValid(); } if (allValid) { return files; } } if (virtualFile == null) { return null; } Set<PsiFile> possibleAnnotationsXmls = new THashSet<PsiFile>(); for (VirtualFile root : getExternalAnnotationsRoots(virtualFile)) { final VirtualFile ext = root.findFileByRelativePath(packageName.replace('.', '/') + "/" + ANNOTATIONS_XML); if (ext == null) continue; final PsiFile psiFile = myPsiManager.findFile(ext); if (psiFile == null) continue; possibleAnnotationsXmls.add(psiFile); } List<PsiFile> result; if (possibleAnnotationsXmls.isEmpty()) { myExternalAnnotations.put(virtualFile, NULL_LIST); result = null; } else { result = new SmartList<PsiFile>(possibleAnnotationsXmls); // sorting by writability: writable go first Collections.sort( result, new Comparator<PsiFile>() { @Override public int compare(PsiFile f1, PsiFile f2) { boolean w1 = f1.isWritable(); boolean w2 = f2.isWritable(); if (w1 == w2) { return 0; } return w1 ? -1 : 1; } }); myExternalAnnotations.put(virtualFile, result); } return result; }
@Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { return file != null && file.isValid(); }
@Override public PsiFile getContainingFile() { PsiFile file = SharedImplUtil.getContainingFile(this); if (file == null || !file.isValid()) throw new PsiInvalidElementAccessException(this); return file; }