Search in sources :

Example 1 with TreeBackedLighterAST

use of com.intellij.lang.TreeBackedLighterAST in project intellij-community by JetBrains.

the class DuplicatesInspectionBase method checkFile.

@Nullable
@Override
public ProblemDescriptor[] checkFile(@NotNull final PsiFile psiFile, @NotNull final InspectionManager manager, final boolean isOnTheFly) {
    final VirtualFile virtualFile = psiFile.getVirtualFile();
    if (!(virtualFile instanceof VirtualFileWithId) || /*!isOnTheFly || */
    !DuplicatesIndex.ourEnabled)
        return ProblemDescriptor.EMPTY_ARRAY;
    final DuplicatesProfile profile = DuplicatesIndex.findDuplicatesProfile(psiFile.getFileType());
    if (profile == null)
        return ProblemDescriptor.EMPTY_ARRAY;
    final Ref<DuplicatedCodeProcessor> myProcessorRef = new Ref<>();
    final FileASTNode node = psiFile.getNode();
    boolean usingLightProfile = profile instanceof LightDuplicateProfile && node.getElementType() instanceof ILightStubFileElementType && DuplicatesIndex.ourEnabledLightProfiles;
    if (usingLightProfile) {
        LighterAST ast = node.getLighterAST();
        ((LightDuplicateProfile) profile).process(ast, new LightDuplicateProfile.Callback() {

            DuplicatedCodeProcessor<LighterASTNode> myProcessor;

            @Override
            public void process(int hash, int hash2, @NotNull final LighterAST ast, @NotNull final LighterASTNode... nodes) {
                class LightDuplicatedCodeProcessor extends DuplicatedCodeProcessor<LighterASTNode> {

                    private LightDuplicatedCodeProcessor(VirtualFile file, Project project) {
                        super(file, project, myFilterOutGeneratedCode);
                    }

                    @Override
                    protected TextRange getRangeInElement(LighterASTNode node) {
                        return null;
                    }

                    @Override
                    protected PsiElement getPsi(LighterASTNode node) {
                        return ((TreeBackedLighterAST) ast).unwrap(node).getPsi();
                    }

                    @Override
                    protected int getStartOffset(LighterASTNode node) {
                        return node.getStartOffset();
                    }

                    @Override
                    protected int getEndOffset(LighterASTNode node) {
                        return node.getEndOffset();
                    }

                    @Override
                    protected boolean isLightProfile() {
                        return true;
                    }
                }
                if (myProcessor == null) {
                    myProcessor = new LightDuplicatedCodeProcessor(virtualFile, psiFile.getProject());
                    myProcessorRef.set(myProcessor);
                }
                myProcessor.process(hash, hash2, nodes[0]);
            }
        });
    } else {
        final DuplocatorState state = profile.getDuplocatorState(psiFile.getLanguage());
        profile.createVisitor(new FragmentsCollector() {

            DuplicatedCodeProcessor<PsiFragment> myProcessor;

            @Override
            public void add(int hash, final int cost, @Nullable final PsiFragment frag) {
                if (!DuplicatesIndex.isIndexedFragment(frag, cost, profile, state)) {
                    return;
                }
                class OldDuplicatedCodeProcessor extends DuplicatedCodeProcessor<PsiFragment> {

                    private OldDuplicatedCodeProcessor(VirtualFile file, Project project) {
                        super(file, project, myFilterOutGeneratedCode);
                    }

                    @Override
                    protected TextRange getRangeInElement(PsiFragment node) {
                        PsiElement[] elements = node.getElements();
                        TextRange rangeInElement = null;
                        if (elements.length > 1) {
                            PsiElement lastElement = elements[elements.length - 1];
                            rangeInElement = new TextRange(elements[0].getStartOffsetInParent(), lastElement.getStartOffsetInParent() + lastElement.getTextLength());
                        }
                        return rangeInElement;
                    }

                    @Override
                    protected PsiElement getPsi(PsiFragment node) {
                        PsiElement[] elements = node.getElements();
                        return elements.length > 1 ? elements[0].getParent() : elements[0];
                    }

                    @Override
                    protected int getStartOffset(PsiFragment node) {
                        return node.getStartOffset();
                    }

                    @Override
                    protected int getEndOffset(PsiFragment node) {
                        return node.getEndOffset();
                    }

                    @Override
                    protected boolean isLightProfile() {
                        return false;
                    }
                }
                if (myProcessor == null) {
                    myProcessor = new OldDuplicatedCodeProcessor(virtualFile, psiFile.getProject());
                    myProcessorRef.set(myProcessor);
                }
                myProcessor.process(hash, 0, frag);
            }
        }, true).visitNode(psiFile);
    }
    DuplicatedCodeProcessor<?> processor = myProcessorRef.get();
    final SmartList<ProblemDescriptor> descriptors = new SmartList<>();
    if (processor != null) {
        final VirtualFile baseDir = psiFile.getProject().getBaseDir();
        for (Map.Entry<Integer, TextRange> entry : processor.reportedRanges.entrySet()) {
            final Integer offset = entry.getKey();
            if (!usingLightProfile && processor.fragmentSize.get(offset) < MIN_FRAGMENT_SIZE)
                continue;
            final VirtualFile file = processor.reportedFiles.get(offset);
            String path = null;
            if (file.equals(virtualFile))
                path = "this file";
            else if (baseDir != null) {
                path = VfsUtilCore.getRelativePath(file, baseDir);
            }
            if (path == null) {
                path = file.getPath();
            }
            String message = "Found duplicated code in " + path;
            PsiElement targetElement = processor.reportedPsi.get(offset);
            TextRange rangeInElement = entry.getValue();
            final int offsetInOtherFile = processor.reportedOffsetInOtherFiles.get(offset);
            LocalQuickFix fix = createNavigateToDupeFix(file, offsetInOtherFile);
            long hash = processor.fragmentHash.get(offset);
            LocalQuickFix viewAllDupesFix = hash != 0 ? createShowOtherDupesFix(virtualFile, offset, (int) hash, (int) (hash >> 32), psiFile.getProject()) : null;
            ProblemDescriptor descriptor = manager.createProblemDescriptor(targetElement, rangeInElement, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, fix, viewAllDupesFix);
            descriptors.add(descriptor);
        }
    }
    return descriptors.isEmpty() ? null : descriptors.toArray(new ProblemDescriptor[descriptors.size()]);
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) DuplicatesProfile(com.intellij.dupLocator.DuplicatesProfile) ILightStubFileElementType(com.intellij.psi.tree.ILightStubFileElementType) FileASTNode(com.intellij.lang.FileASTNode) PsiFragment(com.intellij.dupLocator.util.PsiFragment) FragmentsCollector(com.intellij.dupLocator.treeHash.FragmentsCollector) VirtualFileWithId(com.intellij.openapi.vfs.VirtualFileWithId) LightDuplicateProfile(com.intellij.dupLocator.LightDuplicateProfile) PsiElement(com.intellij.psi.PsiElement) LighterASTNode(com.intellij.lang.LighterASTNode) TreeBackedLighterAST(com.intellij.lang.TreeBackedLighterAST) LighterAST(com.intellij.lang.LighterAST) TextRange(com.intellij.openapi.util.TextRange) DuplocatorState(com.intellij.dupLocator.DuplocatorState) Project(com.intellij.openapi.project.Project) Ref(com.intellij.openapi.util.Ref) TreeBackedLighterAST(com.intellij.lang.TreeBackedLighterAST) SmartList(com.intellij.util.SmartList) TIntLongHashMap(gnu.trove.TIntLongHashMap) Map(java.util.Map) TIntObjectHashMap(gnu.trove.TIntObjectHashMap) TIntIntHashMap(gnu.trove.TIntIntHashMap) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) Nullable(org.jetbrains.annotations.Nullable) Nullable(org.jetbrains.annotations.Nullable)

Example 2 with TreeBackedLighterAST

use of com.intellij.lang.TreeBackedLighterAST in project intellij-community by JetBrains.

the class StubTreeBuilder method buildStubTree.

@Nullable
public static Stub buildStubTree(final FileContent inputData) {
    Stub data = inputData.getUserData(stubElementKey);
    if (data != null)
        return data;
    //noinspection SynchronizationOnLocalVariableOrMethodParameter
    synchronized (inputData) {
        data = inputData.getUserData(stubElementKey);
        if (data != null)
            return data;
        final FileType fileType = inputData.getFileType();
        final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType);
        if (builder != null) {
            data = builder.buildStubTree(inputData);
            if (data instanceof PsiFileStubImpl && !((PsiFileStubImpl) data).rootsAreSet()) {
                ((PsiFileStubImpl) data).setStubRoots(new PsiFileStub[] { (PsiFileStubImpl) data });
            }
        } else {
            CharSequence contentAsText = inputData.getContentAsText();
            FileContentImpl fileContent = (FileContentImpl) inputData;
            PsiFile psi = fileContent.getPsiFileForPsiDependentIndex();
            final FileViewProvider viewProvider = psi.getViewProvider();
            psi = viewProvider.getStubBindingRoot();
            psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, contentAsText);
            // if we load AST, it should be easily gc-able. See PsiFileImpl.createTreeElementPointer()
            psi.getManager().startBatchFilesProcessingMode();
            try {
                IStubFileElementType stubFileElementType = ((PsiFileImpl) psi).getElementTypeForStubBuilder();
                if (stubFileElementType != null) {
                    final StubBuilder stubBuilder = stubFileElementType.getBuilder();
                    if (stubBuilder instanceof LightStubBuilder) {
                        LightStubBuilder.FORCED_AST.set(fileContent.getLighterASTForPsiDependentIndex());
                    }
                    data = stubBuilder.buildStubTree(psi);
                    final List<Pair<IStubFileElementType, PsiFile>> stubbedRoots = getStubbedRoots(viewProvider);
                    final List<PsiFileStub> stubs = new ArrayList<>(stubbedRoots.size());
                    stubs.add((PsiFileStub) data);
                    for (Pair<IStubFileElementType, PsiFile> stubbedRoot : stubbedRoots) {
                        final PsiFile secondaryPsi = stubbedRoot.second;
                        if (psi == secondaryPsi)
                            continue;
                        final StubBuilder stubbedRootBuilder = stubbedRoot.first.getBuilder();
                        if (stubbedRootBuilder instanceof LightStubBuilder) {
                            LightStubBuilder.FORCED_AST.set(new TreeBackedLighterAST(secondaryPsi.getNode()));
                        }
                        final StubElement element = stubbedRootBuilder.buildStubTree(secondaryPsi);
                        if (element instanceof PsiFileStub) {
                            stubs.add((PsiFileStub) element);
                        }
                    }
                    final PsiFileStub[] stubsArray = stubs.toArray(new PsiFileStub[stubs.size()]);
                    for (PsiFileStub stub : stubsArray) {
                        if (stub instanceof PsiFileStubImpl) {
                            ((PsiFileStubImpl) stub).setStubRoots(stubsArray);
                        }
                    }
                }
            } finally {
                psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, null);
                psi.getManager().finishBatchFilesProcessingMode();
            }
        }
        inputData.putUserData(stubElementKey, data);
        return data;
    }
}
Also used : IStubFileElementType(com.intellij.psi.tree.IStubFileElementType) PsiFileImpl(com.intellij.psi.impl.source.PsiFileImpl) ArrayList(java.util.ArrayList) StubBuilder(com.intellij.psi.StubBuilder) FileViewProvider(com.intellij.psi.FileViewProvider) FileType(com.intellij.openapi.fileTypes.FileType) TreeBackedLighterAST(com.intellij.lang.TreeBackedLighterAST) PsiFile(com.intellij.psi.PsiFile) FileContentImpl(com.intellij.util.indexing.FileContentImpl) Pair(com.intellij.openapi.util.Pair) Nullable(org.jetbrains.annotations.Nullable)

Example 3 with TreeBackedLighterAST

use of com.intellij.lang.TreeBackedLighterAST in project intellij-community by JetBrains.

the class FileContentImpl method getLighterASTForPsiDependentIndex.

@NotNull
public LighterAST getLighterASTForPsiDependentIndex() {
    LighterAST lighterAST = getUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY);
    if (lighterAST == null) {
        FileASTNode node = getPsiFileForPsiDependentIndex().getNode();
        lighterAST = myLighterASTShouldBeThreadSafe ? new TreeBackedLighterAST(node) : node.getLighterAST();
        putUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY, lighterAST);
    }
    return lighterAST;
}
Also used : FileASTNode(com.intellij.lang.FileASTNode) TreeBackedLighterAST(com.intellij.lang.TreeBackedLighterAST) TreeBackedLighterAST(com.intellij.lang.TreeBackedLighterAST) LighterAST(com.intellij.lang.LighterAST) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

TreeBackedLighterAST (com.intellij.lang.TreeBackedLighterAST)3 FileASTNode (com.intellij.lang.FileASTNode)2 LighterAST (com.intellij.lang.LighterAST)2 Nullable (org.jetbrains.annotations.Nullable)2 DuplicatesProfile (com.intellij.dupLocator.DuplicatesProfile)1 DuplocatorState (com.intellij.dupLocator.DuplocatorState)1 LightDuplicateProfile (com.intellij.dupLocator.LightDuplicateProfile)1 FragmentsCollector (com.intellij.dupLocator.treeHash.FragmentsCollector)1 PsiFragment (com.intellij.dupLocator.util.PsiFragment)1 LighterASTNode (com.intellij.lang.LighterASTNode)1 FileType (com.intellij.openapi.fileTypes.FileType)1 Project (com.intellij.openapi.project.Project)1 Pair (com.intellij.openapi.util.Pair)1 Ref (com.intellij.openapi.util.Ref)1 TextRange (com.intellij.openapi.util.TextRange)1 VirtualFile (com.intellij.openapi.vfs.VirtualFile)1 VirtualFileWithId (com.intellij.openapi.vfs.VirtualFileWithId)1 FileViewProvider (com.intellij.psi.FileViewProvider)1 PsiElement (com.intellij.psi.PsiElement)1 PsiFile (com.intellij.psi.PsiFile)1