Don't mark compiler-created PSI elements as generated

This saves some memory on storing the generated flag in the PsiElement
userdata and time required to store the flag.
This commit is contained in:
Dmitry Jemerov
2017-03-21 17:53:58 +01:00
parent dc3aa26e3f
commit 3c7678092e
14 changed files with 26 additions and 18 deletions
@@ -161,6 +161,6 @@ object CodegenUtil {
val fakeFunctionCall = StringBuilder("callableReferenceFakeCall(") val fakeFunctionCall = StringBuilder("callableReferenceFakeCall(")
fakeFunctionCall.append(referencedFunction.valueParameters.map { "p${it.index}" }.joinToString(", ")) fakeFunctionCall.append(referencedFunction.valueParameters.map { "p${it.index}" }.joinToString(", "))
fakeFunctionCall.append(")") fakeFunctionCall.append(")")
return KtPsiFactory(project).createExpression(fakeFunctionCall.toString()) as KtCallExpression return KtPsiFactory(project, markGenerated = false).createExpression(fakeFunctionCall.toString()) as KtCallExpression
} }
} }
@@ -4885,7 +4885,7 @@ The "returned" value of try expression with no finally is either the last expres
} }
private Call makeFakeCall(ReceiverValue initializerAsReceiver) { private Call makeFakeCall(ReceiverValue initializerAsReceiver) {
KtSimpleNameExpression fake = KtPsiFactoryKt.KtPsiFactory(state.getProject()).createSimpleName("fake"); KtSimpleNameExpression fake = KtPsiFactoryKt.KtPsiFactory(state.getProject(), false).createSimpleName("fake");
return CallMaker.makeCall(fake, initializerAsReceiver); return CallMaker.makeCall(fake, initializerAsReceiver);
} }
@@ -173,7 +173,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
) { ) {
if (receiver == null) return null; if (receiver == null) return null;
KtExpression receiverExpression = KtPsiFactoryKt.KtPsiFactory(state.getProject()).createExpression("callableReferenceFakeReceiver"); KtExpression receiverExpression = KtPsiFactoryKt.KtPsiFactory(state.getProject(), false).createExpression("callableReferenceFakeReceiver");
codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature, codegen)); codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature, codegen));
return ExpressionReceiver.Companion.create(receiverExpression, receiver.getType(), BindingContext.EMPTY); return ExpressionReceiver.Companion.create(receiverExpression, receiver.getType(), BindingContext.EMPTY);
} }
@@ -137,7 +137,7 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
newCall.recordValueArgument(newCandidateDescriptor.valueParameters[it.key.index], it.value) newCall.recordValueArgument(newCandidateDescriptor.valueParameters[it.key.index], it.value)
} }
val psiFactory = KtPsiFactory(project) val psiFactory = KtPsiFactory(project, markGenerated = false)
val arguments = psiFactory.createCallArguments("(this)").arguments.single() val arguments = psiFactory.createCallArguments("(this)").arguments.single()
val thisExpression = arguments.getArgumentExpression()!! val thisExpression = arguments.getArgumentExpression()!!
newCall.recordValueArgument( newCall.recordValueArgument(
@@ -43,7 +43,7 @@ public class KtImportsFactory {
return directive; return directive;
} }
KtImportDirective createdDirective = KtPsiFactoryKt.KtPsiFactory(project).createImportDirective(importPath); KtImportDirective createdDirective = KtPsiFactoryKt.KtPsiFactory(project, false).createImportDirective(importPath);
importsCache.put(importPath, createdDirective); importsCache.put(importPath, createdDirective);
return createdDirective; return createdDirective;
@@ -33,8 +33,11 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.ImportPath
fun KtPsiFactory(project: Project?): KtPsiFactory = KtPsiFactory(project!!) @JvmOverloads
fun KtPsiFactory(elementForProject: PsiElement): KtPsiFactory = KtPsiFactory(elementForProject.project) fun KtPsiFactory(project: Project?, markGenerated: Boolean = true): KtPsiFactory = KtPsiFactory(project!!, markGenerated)
@JvmOverloads
fun KtPsiFactory(elementForProject: PsiElement, markGenerated: Boolean = true): KtPsiFactory = KtPsiFactory(elementForProject.project, markGenerated)
private val DO_NOT_ANALYZE_NOTIFICATION = "This file was created by KtPsiFactory and should not be analyzed\n" + private val DO_NOT_ANALYZE_NOTIFICATION = "This file was created by KtPsiFactory and should not be analyzed\n" +
"Use createAnalyzableFile to create file that can be analyzed\n" "Use createAnalyzableFile to create file that can be analyzed\n"
@@ -43,7 +46,12 @@ var KtFile.doNotAnalyze: String? by UserDataProperty(Key.create("DO_NOT_ANALYZE"
var KtFile.analysisContext: PsiElement? by UserDataProperty(Key.create("ANALYSIS_CONTEXT")) var KtFile.analysisContext: PsiElement? by UserDataProperty(Key.create("ANALYSIS_CONTEXT"))
var PsiFile.moduleInfo: ModuleInfo? by UserDataProperty(Key.create("MODULE_INFO")) var PsiFile.moduleInfo: ModuleInfo? by UserDataProperty(Key.create("MODULE_INFO"))
class KtPsiFactory(private val project: Project) { /**
* @param markGenerated This needs to be set to true if the `KtPsiFactory` is going to be used for creating elements that are going
* to be inserted in the user source code (this ensures that the elements will be formatted correctly). In other cases, `markGenerated`
* should be false, which saves time and memory.
*/
class KtPsiFactory @JvmOverloads constructor(private val project: Project, val markGenerated: Boolean = true) {
fun createValKeyword(): PsiElement { fun createValKeyword(): PsiElement {
val property = createProperty("val x = 1") val property = createProperty("val x = 1")
@@ -197,7 +205,7 @@ class KtPsiFactory(private val project: Project) {
} }
private fun doCreateFile(fileName: String, text: String): KtFile { private fun doCreateFile(fileName: String, text: String): KtFile {
return PsiFileFactory.getInstance(project).createFileFromText(fileName, KotlinFileType.INSTANCE, text, LocalTimeCounter.currentTime(), false) as KtFile return PsiFileFactory.getInstance(project).createFileFromText(fileName, KotlinFileType.INSTANCE, text, LocalTimeCounter.currentTime(), false, markGenerated) as KtFile
} }
fun createFile(fileName: String, text: String): KtFile { fun createFile(fileName: String, text: String): KtFile {
@@ -422,7 +422,7 @@ public class BodyResolver {
return; return;
} }
KtInitializerList ktInitializerList = new KtPsiFactory(project).createEnumEntryInitializerList(); KtInitializerList ktInitializerList = new KtPsiFactory(project, false).createEnumEntryInitializerList();
KtSuperTypeCallEntry ktCallEntry = (KtSuperTypeCallEntry) ktInitializerList.getInitializers().get(0); KtSuperTypeCallEntry ktCallEntry = (KtSuperTypeCallEntry) ktInitializerList.getInitializers().get(0);
Call call = CallMaker.makeConstructorCallWithoutTypeArguments(ktCallEntry); Call call = CallMaker.makeConstructorCallWithoutTypeArguments(ktCallEntry);
trace.record(BindingContext.TYPE, ktCallEntry.getTypeReference(), enumClassDescriptor.getDefaultType()); trace.record(BindingContext.TYPE, ktCallEntry.getTypeReference(), enumClassDescriptor.getDefaultType());
@@ -280,7 +280,7 @@ class DelegatedPropertyResolver(
val hasThis = propertyDescriptor.extensionReceiverParameter != null || propertyDescriptor.dispatchReceiverParameter != null val hasThis = propertyDescriptor.extensionReceiverParameter != null || propertyDescriptor.dispatchReceiverParameter != null
val arguments = Lists.newArrayList<KtExpression>() val arguments = Lists.newArrayList<KtExpression>()
val psiFactory = KtPsiFactory(delegateExpression) val psiFactory = KtPsiFactory(delegateExpression, markGenerated = false)
arguments.add(psiFactory.createExpression(if (hasThis) "this" else "null")) arguments.add(psiFactory.createExpression(if (hasThis) "this" else "null"))
arguments.add(psiFactory.createExpressionForProperty()) arguments.add(psiFactory.createExpressionForProperty())
@@ -313,7 +313,7 @@ class DelegatedPropertyResolver(
val expectedType = TypeUtils.NO_EXPECTED_TYPE val expectedType = TypeUtils.NO_EXPECTED_TYPE
val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, expectedType) val context = ExpressionTypingContext.newContext(trace, initializerScope, dataFlowInfo, expectedType)
val propertyHasReceiver = propertyDescriptor.dispatchReceiverParameter != null val propertyHasReceiver = propertyDescriptor.dispatchReceiverParameter != null
val arguments = KtPsiFactory(delegateExpression).run { val arguments = KtPsiFactory(delegateExpression, markGenerated = false).run {
listOf( listOf(
createExpression(if (propertyHasReceiver) "this" else "null"), createExpression(if (propertyHasReceiver) "this" else "null"),
createExpressionForProperty() createExpressionForProperty()
@@ -107,7 +107,7 @@ public class CallTransformer {
this.explicitExtensionReceiver = explicitExtensionReceiver; this.explicitExtensionReceiver = explicitExtensionReceiver;
this.calleeExpressionAsDispatchReceiver = calleeExpressionAsDispatchReceiver; this.calleeExpressionAsDispatchReceiver = calleeExpressionAsDispatchReceiver;
this.fakeInvokeExpression = this.fakeInvokeExpression =
(KtSimpleNameExpression) KtPsiFactoryKt.KtPsiFactory(call.getCallElement()) (KtSimpleNameExpression) KtPsiFactoryKt.KtPsiFactory(call.getCallElement(), false)
.createExpression(OperatorNameConventions.INVOKE.asString()); .createExpression(OperatorNameConventions.INVOKE.asString());
itIsVariableAsFunctionCall = functionCall; itIsVariableAsFunctionCall = functionCall;
} }
@@ -1193,7 +1193,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
expression, expression,
receiver, receiver,
// semantically, a call to `==` is a safe call // semantically, a call to `==` is a safe call
new KtPsiFactory(expression.getProject()).createSafeCallNode(), new KtPsiFactory(expression.getProject(), false).createSafeCallNode(),
operationSign, operationSign,
Collections.singletonList(right) Collections.singletonList(right)
); );
@@ -119,7 +119,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
return getTypeInfoWhenOnlyOneBranchIsPresent( return getTypeInfoWhenOnlyOneBranchIsPresent(
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression); elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
} }
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression); KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression, false);
KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch); KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
KtBlockExpression elseBlock = psiFactory.wrapInABlockWrapper(elseBranch); KtBlockExpression elseBlock = psiFactory.wrapInABlockWrapper(elseBranch);
Call callForIf = createCallForSpecialConstruction(ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock)); Call callForIf = createCallForSpecialConstruction(ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock));
@@ -262,7 +262,7 @@ class DoubleColonExpressionResolver(
private fun KtQualifiedExpression.buildNewExpressionForReservedGenericPropertyCallChainResolution(): KtExpression? { private fun KtQualifiedExpression.buildNewExpressionForReservedGenericPropertyCallChainResolution(): KtExpression? {
val parts = this.getQualifierChainParts()?.map { it.getQualifiedNameStringPart() ?: return null } ?: return null val parts = this.getQualifierChainParts()?.map { it.getQualifiedNameStringPart() ?: return null } ?: return null
val qualifiedExpressionText = parts.joinToString(separator = ".") val qualifiedExpressionText = parts.joinToString(separator = ".")
return KtPsiFactory(this).createExpression(qualifiedExpressionText) return KtPsiFactory(this, markGenerated = false).createExpression(qualifiedExpressionText)
} }
private fun resolveReservedExpressionOnLHS(expression: KtExpression, c: ExpressionTypingContext): DoubleColonLHS.Expression? { private fun resolveReservedExpressionOnLHS(expression: KtExpression, c: ExpressionTypingContext): DoubleColonLHS.Expression? {
@@ -96,7 +96,7 @@ public class ExpressionTypingUtils {
@NotNull String argumentName, @NotNull String argumentName,
@NotNull KotlinType argumentType @NotNull KotlinType argumentType
) { ) {
KtExpression fakeExpression = KtPsiFactoryKt.KtPsiFactory(project).createExpression(argumentName); KtExpression fakeExpression = KtPsiFactoryKt.KtPsiFactory(project, false).createExpression(argumentName);
trace.recordType(fakeExpression, argumentType); trace.recordType(fakeExpression, argumentType);
trace.record(PROCESSED, fakeExpression); trace.record(PROCESSED, fakeExpression);
return fakeExpression; return fakeExpression;
@@ -108,7 +108,7 @@ class FakeCallResolver(
callElement: KtExpression, callElement: KtExpression,
onComplete: (KtSimpleNameExpression, Boolean) -> Unit = { _, _ -> } onComplete: (KtSimpleNameExpression, Boolean) -> Unit = { _, _ -> }
): Pair<Call, OverloadResolutionResults<FunctionDescriptor>> { ): Pair<Call, OverloadResolutionResults<FunctionDescriptor>> {
val fakeCalleeExpression = KtPsiFactory(project).createSimpleName(name.asString()) val fakeCalleeExpression = KtPsiFactory(project, markGenerated = false).createSimpleName(name.asString())
val call = CallMaker.makeCallWithExpressions( val call = CallMaker.makeCallWithExpressions(
callElement, receiver, /* callOperationNode = */ null, fakeCalleeExpression, valueArguments callElement, receiver, /* callOperationNode = */ null, fakeCalleeExpression, valueArguments
) )