From a4c164361a416a29f95b6ad8424cf88ffbc2bbe0 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 30 Oct 2013 16:51:02 +0400 Subject: [PATCH] injected smart pointers --- .../InjectedSelfElementInfo.java | 64 ++++++++++++------- .../impl/smartPointers/SelfElementInfo.java | 11 ++-- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java index cd8be282b19c..ce343b517726 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -46,7 +46,7 @@ class InjectedSelfElementInfo extends SelfElementInfo { @NotNull PsiElement hostContext) { super(project, hostContext); assert containingFile.getViewProvider() instanceof FreeThreadedFileViewProvider : "element parameter must be an injected element: "+injectedElement+"; "+containingFile; - ProperTextRange.assertProperRange(injectedRange); + TextRange.assertProperRange(injectedRange); assert containingFile.getTextRange().contains(injectedRange) : "Injected range outside the file: "+injectedRange +"; file: "+containingFile.getTextRange(); TextRange hostRange = InjectedLanguageManager.getInstance(project).injectedToHost(injectedElement, injectedRange); @@ -54,8 +54,8 @@ class InjectedSelfElementInfo extends SelfElementInfo { assert !(hostFile.getViewProvider() instanceof FreeThreadedFileViewProvider) : "hostContext parameter must not be and injected element: "+hostContext; SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project); myInjectedFileRangeInHostFile = smartPointerManager.createSmartPsiFileRangePointer(hostFile, hostRange); - anchorClass = containingFile.findElementAt(injectedRange.getStartOffset()).getClass(); anchorLanguage = containingFile.getLanguage(); + anchorClass = injectedElement.getClass(); //containingFile.findElementAt(injectedRange.getStartOffset()).getClass(); } @Override @@ -73,32 +73,40 @@ class InjectedSelfElementInfo extends SelfElementInfo { @Override public PsiElement restoreElement() { if (!mySyncMarkerIsValid) return null; - PsiFile file = restoreFileFromVirtual(myVirtualFile, myProject, myLanguage); - if (file == null || !file.isValid()) return null; + PsiFile hostFile = restoreFileFromVirtual(myVirtualFile, myProject, myLanguage); + if (hostFile == null || !hostFile.isValid()) return null; - PsiElement hostContext = restoreFromFile(file); + PsiElement hostContext = restoreFromFile(hostFile); if (hostContext == null) return null; Segment segment = myInjectedFileRangeInHostFile.getRange(); if (segment == null) return null; final TextRange rangeInHostFile = TextRange.create(segment); - final Ref result = new Ref(); + PsiElement result = null; + PsiFile injectedPsi = getInjectedFileIn(hostContext, hostFile, rangeInHostFile); + if (injectedPsi != null) { + Document document = PsiDocumentManager.getInstance(getProject()).getDocument(injectedPsi); + int start = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getStartOffset()); + int end = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getEndOffset()); + result = findElementInside(injectedPsi, start, end, anchorClass, anchorLanguage); + } + + return result; + } + + private PsiFile getInjectedFileIn(@NotNull final PsiElement hostContext, + @NotNull final PsiFile hostFile, final TextRange rangeInHostFile + ) { final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(getProject()); - PsiFile hostFile = hostContext.getContainingFile(); - if (hostFile == null) return null; - - PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { + final PsiFile[] result = {null}; + final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { @Override public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { - if (result.get() != null) return; TextRange hostRange = manager.injectedToHost(injectedPsi, new TextRange(0, injectedPsi.getTextLength())); Document document = PsiDocumentManager.getInstance(getProject()).getDocument(injectedPsi); if (hostRange.contains(rangeInHostFile) && document instanceof DocumentWindow) { - int start = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getStartOffset()); - int end = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getEndOffset()); - PsiElement element = findElementInside(injectedPsi, start, end, anchorClass, anchorLanguage); - result.set(element); + result[0] = injectedPsi; } } }; @@ -123,7 +131,7 @@ class InjectedSelfElementInfo extends SelfElementInfo { } } - return result.get(); + return result[0]; } @Override @@ -137,17 +145,29 @@ class InjectedSelfElementInfo extends SelfElementInfo { @Override public PsiFile restoreFile() { - PsiElement element = restoreElement(); - return element == null ? null : element.getContainingFile(); + PsiFile hostFile = restoreFileFromVirtual(myVirtualFile, myProject, myLanguage); + if (hostFile == null || !hostFile.isValid()) return null; + + PsiElement hostContext = restoreFromFile(hostFile); + if (hostContext == null) return null; + + Segment segment = myInjectedFileRangeInHostFile.getRange(); + if (segment == null) return null; + final TextRange rangeInHostFile = TextRange.create(segment); + return getInjectedFileIn(hostContext, hostFile, rangeInHostFile); } public ProperTextRange getInjectedRange() { + PsiFile hostFile = restoreFileFromVirtual(myVirtualFile, myProject, myLanguage); + if (hostFile == null || !hostFile.isValid()) return null; + + PsiElement hostContext = restoreFromFile(hostFile); + if (hostContext == null) return null; + Segment hostElementRange = myInjectedFileRangeInHostFile.getRange(); if (hostElementRange == null) return null; - PsiElement injectedElement = restoreElement(); - if (injectedElement == null) return null; - PsiFile injectedFile = injectedElement.getContainingFile(); + PsiFile injectedFile = restoreFile(); if (injectedFile == null) return null; VirtualFile virtualFile = injectedFile.getVirtualFile(); DocumentWindow documentWindow = virtualFile instanceof VirtualFileWindow ? ((VirtualFileWindow)virtualFile).getDocumentWindow() : null; diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java index 18dda8840988..f61cab6c550b 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -166,7 +166,11 @@ public class SelfElementInfo implements SmartPointerElementInfo { return restoreFileFromVirtual(myVirtualFile, myProject, myLanguage); } - protected static PsiElement findElementInside(@NotNull PsiFile file, int syncStartOffset, int syncEndOffset, @NotNull Class type, @NotNull Language language) { + protected static PsiElement findElementInside(@NotNull PsiFile file, + int syncStartOffset, + int syncEndOffset, + @NotNull Class type, + @NotNull Language language) { PsiElement anchor = file.getViewProvider().findElementAt(syncStartOffset, language); if (anchor == null) return null; @@ -185,8 +189,7 @@ public class SelfElementInfo implements SmartPointerElementInfo { range = anchor.getTextRange(); } - if (range.getEndOffset() == syncEndOffset) return anchor; - return null; + return range.getEndOffset() == syncEndOffset ? anchor : null; } private RangeMarker getMarker() {