/*
* Copyright 2000-2017 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 com.intellij.psi.impl.source;
import com.intellij.openapi.util.Getter;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.stubs.PsiFileStubImpl;
import com.intellij.psi.stubs.StubTree;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.Reference;
import java.util.Set;
/**
* @author peter
*/
final class FileTrees {
private final Reference<StubTree> myStub;
private final Getter<FileElement> myTreeElementPointer; // SoftReference/WeakReference to ASTNode or a strong reference to a tree if the file is a DummyHolder
final boolean astLoaded;
final boolean useStrongRefs;
private FileTrees(@Nullable Reference<StubTree> stub, @Nullable Getter<FileElement> ast, boolean astLoaded, boolean useStrongRefs) {
this.myStub = stub;
this.myTreeElementPointer = ast;
this.astLoaded = astLoaded;
this.useStrongRefs = useStrongRefs;
}
@Nullable
StubTree derefStub() {
return SoftReference.dereference(myStub);
}
@Nullable
FileElement derefTreeElement() {
return SoftReference.deref(myTreeElementPointer);
}
FileTrees switchToStrongRefs() {
return new FileTrees(myStub, myTreeElementPointer, astLoaded, true);
}
FileTrees clearStub(@NotNull String reason) {
StubTree stubHolder = derefStub();
if (stubHolder != null) {
((PsiFileStubImpl<?>)stubHolder.getRoot()).clearPsi(reason);
}
return new FileTrees(null, myTreeElementPointer, astLoaded, useStrongRefs);
}
FileTrees withAst(@NotNull Getter<FileElement> ast) {
return new FileTrees(myStub, ast, true, useStrongRefs);
}
FileTrees withExclusiveStub(@NotNull StubTree stub, Set<PsiFileImpl> allRoots) {
if (derefTreeElement() != null || useStrongRefs) {
throw new RuntimeException(toString() + "; roots=" + allRoots);
}
return new FileTrees(new SoftReference<>(stub), null, false, false);
}
FileTrees withGreenStub(@NotNull StubTree stub, @NotNull PsiFileImpl file) {
if (derefTreeElement() == null || !astLoaded) {
throw new RuntimeException("No AST in file " + file + " of " + file.getClass() + "; " + this);
}
return new FileTrees(new SoftReference<>(stub), myTreeElementPointer, true, useStrongRefs);
}
static FileTrees noStub(@Nullable FileElement ast, @NotNull PsiFileImpl file) {
return new FileTrees(null, ast, ast != null, file instanceof DummyHolder);
}
@Override
public String toString() {
return "FileTrees{" +
"stub=" + (myStub == null ? "noRef" : derefStub()) +
", AST=" + (myTreeElementPointer == null ? "noRef" : derefTreeElement()) +
", astLoaded=" + astLoaded +
", useStrongRefs=" + useStrongRefs +
'}' ;
}
}