From fb08e13da9428c1bafd694b4c9661285be9fa32a Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 25 May 2012 21:05:36 +0400 Subject: [PATCH 01/24] added PseudocodeData to store information about variables for each instruction: initialization and use statuses --- .../lang/cfg/JetFlowInformationProvider.java | 431 ++++-------------- .../jet/lang/cfg/data/DeclarationData.java | 42 ++ .../jet/lang/cfg/data/InstructionData.java | 92 ++++ .../jet/lang/cfg/data/PseudocodeData.java | 331 ++++++++++++++ .../lang/cfg/data/VariableInitializers.java | 100 ++++ .../jet/lang/cfg/data/VariableUseStatus.java | 40 ++ 6 files changed, 689 insertions(+), 347 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index a30b1de310f..a60398498ff 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -19,12 +19,12 @@ package org.jetbrains.jet.lang.cfg; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.data.*; import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.Errors; @@ -50,12 +50,14 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; public class JetFlowInformationProvider { private final Map pseudocodeMap; + private final Map pseudocodeDataMap; private BindingTrace trace; public JetFlowInformationProvider(@NotNull JetDeclaration declaration, @NotNull final JetExpression bodyExpression, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace trace) { this.trace = trace; final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration); - pseudocodeMap = new HashMap(); + pseudocodeMap = new LinkedHashMap(); + pseudocodeDataMap = new HashMap(); final Map representativeInstructions = new HashMap(); final Map loopInfo = Maps.newHashMap(); JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() { @@ -81,7 +83,9 @@ public class JetFlowInformationProvider { @Override public void close() { pseudocodeTrace.close(); - for (Pseudocode pseudocode : pseudocodeMap.values()) { + List values = Lists.newArrayList(pseudocodeMap.values()); + Collections.reverse(values); + for (Pseudocode pseudocode : values) { pseudocode.postProcess(); } } @@ -91,6 +95,17 @@ public class JetFlowInformationProvider { wrappedTrace.close(); } + private PseudocodeData getPseudocodeData(@NotNull JetElement element) { + PseudocodeData pseudocodeData = pseudocodeDataMap.get(element); + if (pseudocodeData == null) { + Pseudocode pseudocode = pseudocodeMap.get(element); + assert pseudocode != null; + pseudocodeData = new PseudocodeData(pseudocode, trace); + pseudocodeDataMap.put(element, pseudocodeData); + } + return pseudocodeData; + } + private void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection returnedExpressions) { Pseudocode pseudocode = pseudocodeMap.get(subroutine); assert pseudocode != null; @@ -214,63 +229,49 @@ public class JetFlowInformationProvider { // Uninitialized variables analysis public void markUninitializedVariables(@NotNull JetElement subroutine, final boolean processLocalDeclaration) { - final Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - - JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, false, true); - - Collection usedVariables = collectUsedVariables(pseudocode); - final Collection declaredVariables = collectDeclaredVariables(subroutine); - Map initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables); - - traverser.collectInformationFromInstructionGraph(Collections.emptyMap(), initialMapForStartInstruction, - new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { - @Override - public Pair, Map> execute( - @NotNull Instruction instruction, - @NotNull Collection> incomingEdgesData) { - - Map enterInstructionData = mergeIncomingEdgesData(incomingEdgesData); - Map exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); - return Pair.create(enterInstructionData, exitInstructionData); - } - }); - final Collection varWithUninitializedErrorGenerated = Sets.newHashSet(); final Collection varWithValReassignErrorGenerated = Sets.newHashSet(); final boolean processClassOrObject = subroutine instanceof JetClassOrObject; - traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy>() { + + final PseudocodeData pseudocodeData = getPseudocodeData(subroutine); + pseudocodeData.traverseInstructionsGraph(true, true, new PseudocodeData.TraverseInstructionGraphStrategy() { @Override - public void execute(@NotNull Instruction instruction, @Nullable Map enterData, @Nullable Map exitData) { - assert enterData != null && exitData != null; - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); + public void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData) { + //todo move to util + VariableDescriptor variableDescriptor = pseudocodeData.extractVariableDescriptorIfAny(instruction, true); if (variableDescriptor == null) return; + if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return; + InstructionData.EdgesData variableInitializers = instructionData.getInitializersMap().get( + variableDescriptor); + if (variableInitializers == null) return; if (instruction instanceof ReadValueInstruction) { JetElement element = ((ReadValueInstruction) instruction).getElement(); boolean error = checkBackingField(variableDescriptor, element); - if (!error && declaredVariables.contains(variableDescriptor)) { - checkIsInitialized(variableDescriptor, element, exitData.get(variableDescriptor), varWithUninitializedErrorGenerated); + if (!error && declarationData.declaredVariables.contains(variableDescriptor)) { + checkIsInitialized(variableDescriptor, element, variableInitializers.getOut(), varWithUninitializedErrorGenerated); } + return; } - else if (instruction instanceof WriteValueInstruction) { - JetElement element = ((WriteValueInstruction) instruction).getlValue(); - boolean error = checkBackingField(variableDescriptor, element); - if (!(element instanceof JetExpression)) return; - if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration - error = checkValReassignment(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), varWithValReassignErrorGenerated); - } - if (!error && processClassOrObject) { - error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor)); - } - if (!error && processClassOrObject) { - checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor)); - } + JetElement element = ((WriteValueInstruction) instruction).getlValue(); + boolean error = checkBackingField(variableDescriptor, element); + if (!(element instanceof JetExpression)) return; + if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration + error = checkValReassignment(variableDescriptor, (JetExpression) element, variableInitializers.getIn(), varWithValReassignErrorGenerated); + } + if (!error && processClassOrObject) { + error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, variableInitializers.getIn(), variableInitializers.getOut()); + } + if (!error && processClassOrObject) { + checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, variableInitializers.getIn(), variableInitializers.getOut()); } } }); - recordInitializedVariables(declaredVariables, traverser.getResultInfo()); - analyzeLocalDeclarations(pseudocode, processLocalDeclaration); + Pseudocode pseudocode = pseudocodeData.getPseudocode(); + recordInitializedVariables(pseudocodeData.getDeclarationData(pseudocode), pseudocodeData.getResultInfo(pseudocode)); + for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + recordInitializedVariables(pseudocodeData.getDeclarationData(localPseudocode), pseudocodeData.getResultInfo(localPseudocode)); + } } private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, @@ -436,12 +437,12 @@ public class JetFlowInformationProvider { return false; } - private void recordInitializedVariables(Collection declaredVariables, Map resultInfo) { - for (Map.Entry entry : resultInfo.entrySet()) { - VariableDescriptor variable = entry.getKey(); - if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) { - VariableInitializers initializers = entry.getValue(); - trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, initializers.isInitialized()); + private void recordInitializedVariables(DeclarationData declarationData, InstructionData instructionData) { + for (VariableDescriptor variable : declarationData.usedVariables) { + if (variable instanceof PropertyDescriptor && declarationData.declaredVariables.contains(variable)) { + InstructionData.EdgesData variableInitializers = instructionData.getInitializersMap().get(variable); + if (variableInitializers == null) return; + trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitializers.getIn().isInitialized()); } } } @@ -455,161 +456,33 @@ public class JetFlowInformationProvider { } } - private Map addVariableInitializerFromCurrentInstructionIfAny(Instruction instruction, Map enterInstructionData) { - Map exitInstructionData = Maps.newHashMap(enterInstructionData); - if (instruction instanceof WriteValueInstruction) { - VariableDescriptor variable = extractVariableDescriptorIfAny(instruction, false); - VariableInitializers enterInitializers = enterInstructionData.get(variable); - VariableInitializers initializationAtThisElement = new VariableInitializers(((WriteValueInstruction) instruction).getElement(), enterInitializers); - exitInstructionData.put(variable, initializationAtThisElement); - } - else if (instruction instanceof VariableDeclarationInstruction) { - VariableDescriptor variable = extractVariableDescriptorIfAny(instruction, false); - VariableInitializers enterInitializers = enterInstructionData.get(variable); - if (enterInitializers == null || !enterInitializers.isInitialized() || !enterInitializers.isDeclared()) { - JetElement element = ((VariableDeclarationInstruction) instruction).getElement(); - if (element instanceof JetProperty) { - JetProperty property = (JetProperty) element; - if (property.getInitializer() == null) { - boolean isInitialized = enterInitializers != null && enterInitializers.isInitialized(); - VariableInitializers variableDeclarationInfo = new VariableInitializers(isInitialized, true); - exitInstructionData.put(variable, variableDeclarationInfo); - } - } - } - } - return exitInstructionData; - } - - private Map mergeIncomingEdgesData(Collection> incomingEdgesData) { - Set variablesInScope = Sets.newHashSet(); - for (Map edgeData : incomingEdgesData) { - variablesInScope.addAll(edgeData.keySet()); - } - - Map enterInstructionData = Maps.newHashMap(); - for (VariableDescriptor variable : variablesInScope) { - Set edgesDataForVariable = Sets.newHashSet(); - for (Map edgeData : incomingEdgesData) { - VariableInitializers initializers = edgeData.get(variable); - if (initializers != null) { - edgesDataForVariable.add(initializers); - } - } - enterInstructionData.put(variable, new VariableInitializers(edgesDataForVariable)); - } - return enterInstructionData; - } - - private Map prepareInitialMapForStartInstruction(Collection usedVariables, Collection declaredVariables) { - Map initialMapForStartInstruction = Maps.newHashMap(); - VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true); - VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false); - - for (VariableDescriptor variable : usedVariables) { - if (declaredVariables.contains(variable)) { - initialMapForStartInstruction.put(variable, isNotInitializedForDeclaredVariable); - } - else { - initialMapForStartInstruction.put(variable, isInitializedForExternalVariable); - } - } - return initialMapForStartInstruction; - } - -//////////////////////////////////////////////////////////////////////////////// - - public void markNotOnlyInvokedFunctionVariables(@NotNull JetElement subroutine, List variables) { - final List functionVariables = Lists.newArrayList(); - for (VariableDescriptor variable : variables) { - if (JetStandardClasses.isFunctionType(variable.getReturnType())) { - functionVariables.add(variable); - } - } - - Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - - JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction, Void enterData, Void exitData) { - if (instruction instanceof ReadValueInstruction) { - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); - if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) { - //check that we only invoke this variable - JetElement element = ((ReadValueInstruction) instruction).getElement(); - if (element instanceof JetSimpleNameExpression && !(element.getParent() instanceof JetCallExpression)) { - trace.report(Errors.FUNCTION_PARAMETERS_OF_INLINE_FUNCTION.on((JetSimpleNameExpression) element, variableDescriptor)); - } - } - } - } - }); - } - //////////////////////////////////////////////////////////////////////////////// // "Unused variable" & "unused value" analyses public void markUnusedVariables(@NotNull JetElement subroutine) { - Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, false); - final Collection declaredVariables = collectDeclaredVariables(subroutine); - Map sinkInstructionData = Maps.newHashMap(); - traverser.collectInformationFromInstructionGraph(Collections.emptyMap(), sinkInstructionData, new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { + final PseudocodeData pseudocodeData = getPseudocodeData(subroutine); + pseudocodeData.traverseInstructionsGraph(true, false, new PseudocodeData.TraverseInstructionGraphStrategy() { @Override - public Pair, Map> execute(@NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { - Map enterResult = Maps.newHashMap(); - for (Map edgeData : incomingEdgesData) { - for (Map.Entry entry : edgeData.entrySet()) { - VariableDescriptor variableDescriptor = entry.getKey(); - VariableStatus variableStatus = entry.getValue(); - enterResult.put(variableDescriptor, variableStatus.merge(enterResult.get(variableDescriptor))); - } - } - Map exitResult = Maps.newHashMap(enterResult); - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); - if (variableDescriptor != null) { - if (instruction instanceof ReadValueInstruction) { - exitResult.put(variableDescriptor, VariableStatus.READ); - } - else if (instruction instanceof WriteValueInstruction) { - VariableStatus variableStatus = enterResult.get(variableDescriptor); - if (variableStatus == null) variableStatus = VariableStatus.UNUSED; - switch(variableStatus) { - case UNUSED: - case ONLY_WRITTEN: - exitResult.put(variableDescriptor, VariableStatus.ONLY_WRITTEN); - break; - case WRITTEN: - case READ: - exitResult.put(variableDescriptor, VariableStatus.WRITTEN); - } - } - } - return new Pair, Map>(enterResult, exitResult); - } - }); - traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy>() { - @Override - public void execute(@NotNull Instruction instruction, @Nullable Map enterData, @Nullable Map exitData) { - assert enterData != null && exitData != null; - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); - if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) || + public void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData) { + VariableDescriptor variableDescriptor = pseudocodeData.extractVariableDescriptorIfAny(instruction, false); + if (variableDescriptor == null || !declarationData.declaredVariables.contains(variableDescriptor) || !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return; - VariableStatus variableStatus = enterData.get(variableDescriptor); + InstructionData.EdgesData statusEdgesData = instructionData.getUseStatusMap().get(variableDescriptor); + VariableUseStatus variableUseStatus = statusEdgesData != null ? statusEdgesData.getIn() : null; if (instruction instanceof WriteValueInstruction) { if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return; JetElement element = ((WriteValueInstruction) instruction).getElement(); - if (variableStatus != VariableStatus.READ) { - if (element instanceof JetBinaryExpression && ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) { + if (variableUseStatus != VariableUseStatus.LAST_READ) { + if (element instanceof JetBinaryExpression && + ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) { JetExpression right = ((JetBinaryExpression) element).getRight(); if (right != null) { trace.report(Errors.UNUSED_VALUE.on(right, right, variableDescriptor)); } } else if (element instanceof JetPostfixExpression) { - IElementType operationToken = ((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType(); + IElementType operationToken = + ((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType(); if (operationToken == JetTokens.PLUSPLUS || operationToken == JetTokens.MINUSMINUS) { trace.report(Errors.UNUSED_CHANGED_VALUE.on(element, element)); } @@ -621,55 +494,48 @@ public class JetFlowInformationProvider { if (element instanceof JetNamedDeclaration) { PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier(); if (nameIdentifier == null) return; - if (variableStatus == null || variableStatus == VariableStatus.UNUSED) { + if (variableUseStatus == null || variableUseStatus == VariableUseStatus.UNUSED) { if (element instanceof JetProperty) { trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor)); } else if (element instanceof JetParameter) { PsiElement psiElement = element.getParent().getParent(); if (psiElement instanceof JetFunction) { - boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement); - DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); - assert descriptor instanceof FunctionDescriptor; + boolean isMain = (psiElement instanceof JetNamedFunction) && + JetMainDetector.isMain((JetNamedFunction) psiElement); + //todo + if (psiElement instanceof JetFunctionLiteral) { + //psiElement = psiElement.getParent(); + return; + } + DeclarationDescriptor descriptor = + trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); + assert descriptor instanceof FunctionDescriptor : psiElement.getText(); FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; - if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) { + if (!isMain && + !functionDescriptor.getModality().isOverridable() && + functionDescriptor.getOverriddenDescriptors().isEmpty()) { trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor)); } } } } - else if (variableStatus == VariableStatus.ONLY_WRITTEN && element instanceof JetProperty) { - trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor)); + else if (variableUseStatus == VariableUseStatus.ONLY_WRITTEN_NEVER_READ && element instanceof JetProperty) { + trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE + .on((JetNamedDeclaration) element, variableDescriptor)); } - else if (variableStatus == VariableStatus.WRITTEN && element instanceof JetProperty) { + else if (variableUseStatus == VariableUseStatus.LAST_WRITTEN && element instanceof JetProperty) { JetExpression initializer = ((JetProperty) element).getInitializer(); if (initializer != null) { trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor)); } } } - } + } }); - } - private static enum VariableStatus { - READ(3), - WRITTEN(2), - ONLY_WRITTEN(1), - UNUSED(0); - - private int importance; - - private VariableStatus(int importance) { - this.importance = importance; - } - - public VariableStatus merge(@Nullable VariableStatus variableStatus) { - if (variableStatus == null || importance > variableStatus.importance) return this; - return variableStatus; - } } //////////////////////////////////////////////////////////////////////////////// @@ -704,133 +570,4 @@ public class JetFlowInformationProvider { } }); } - -//////////////////////////////////////////////////////////////////////////////// -// Util methods 7 - - @Nullable - private VariableDescriptor extractVariableDescriptorIfAny(Instruction instruction, boolean onlyReference) { - JetElement element = null; - if (instruction instanceof ReadValueInstruction) { - element = ((ReadValueInstruction) instruction).getElement(); - } - else if (instruction instanceof WriteValueInstruction) { - element = ((WriteValueInstruction) instruction).getlValue(); - } - else if (instruction instanceof VariableDeclarationInstruction) { - element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); - } - return BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), element, onlyReference); - } - - private Collection collectUsedVariables(Pseudocode pseudocode) { - final Set usedVariables = Sets.newHashSet(); - JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction, Void enterData, Void exitData) { - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); - if (variableDescriptor != null) { - usedVariables.add(variableDescriptor); - } - } - }); - return usedVariables; - } - - private Collection collectDeclaredVariables(JetElement element) { - final Pseudocode pseudocode = pseudocodeMap.get(element); - assert pseudocode != null; - - final Set declaredVariables = Sets.newHashSet(); - JetControlFlowGraphTraverser.create(pseudocode, false, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { - if (instruction instanceof VariableDeclarationInstruction) { - JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); - DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement); - if (descriptor != null) { - assert descriptor instanceof VariableDescriptor; - declaredVariables.add((VariableDescriptor) descriptor); - } - } - } - }); - return declaredVariables; - } - -//////////////////////////////////////////////////////////////////////////////// -// Local class for uninitialized variables analysis - - private static class VariableInitializers { - private Set possibleLocalInitializers = Sets.newHashSet(); - private boolean isInitialized; - private boolean isDeclared; - - public VariableInitializers(boolean isInitialized) { - this(isInitialized, false); - } - - public VariableInitializers(boolean isInitialized, boolean isDeclared) { - this.isInitialized = isInitialized; - this.isDeclared = isDeclared; - } - - public VariableInitializers(JetElement element, @Nullable VariableInitializers previous) { - isInitialized = true; - isDeclared = element instanceof JetProperty || (previous != null && previous.isDeclared()); - possibleLocalInitializers.add(element); - } - - public VariableInitializers(Set edgesData) { - isInitialized = true; - isDeclared = true; - for (VariableInitializers edgeData : edgesData) { - if (!edgeData.isInitialized) { - isInitialized = false; - } - if (!edgeData.isDeclared) { - isDeclared = false; - } - possibleLocalInitializers.addAll(edgeData.possibleLocalInitializers); - } - } - - public Set getPossibleLocalInitializers() { - return possibleLocalInitializers; - } - - public boolean isInitialized() { - return isInitialized; - } - - public boolean isDeclared() { - return isDeclared; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof VariableInitializers)) return false; - - VariableInitializers that = (VariableInitializers) o; - - if (isDeclared != that.isDeclared) return false; - if (isInitialized != that.isInitialized) return false; - if (possibleLocalInitializers != null - ? !possibleLocalInitializers.equals(that.possibleLocalInitializers) - : that.possibleLocalInitializers != null) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = possibleLocalInitializers != null ? possibleLocalInitializers.hashCode() : 0; - result = 31 * result + (isInitialized ? 1 : 0); - result = 31 * result + (isDeclared ? 1 : 0); - return result; - } - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java new file mode 100644 index 00000000000..f22d47136bc --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; + +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.psi.JetElement; + +import java.util.Set; + +/** + * @author svtk + */ +public class DeclarationData { + public final JetElement element; + public final PseudocodeData pseudocodeData; + public final Set declaredVariables; + public final Set usedVariables; + + public DeclarationData(JetElement element, + PseudocodeData data, + Set declaredVariables, + Set usedVariables) { + this.element = element; + pseudocodeData = data; + this.declaredVariables = declaredVariables; + this.usedVariables = usedVariables; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java new file mode 100644 index 00000000000..ec77df1997d --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; + +import com.google.common.collect.Maps; +import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; + +import java.util.Map; + +/** + * @author svtk + */ +public class InstructionData { + public final Instruction instruction; + public final PseudocodeData pseudocodeData; + + private final Map> initializersMap = Maps.newHashMap(); + private final Map> useStatusMap = Maps.newHashMap(); + + public InstructionData(@NotNull PseudocodeData data, @NotNull Instruction instruction, + @NotNull Pair, Map> pairOfVariableInitializersMap, + @NotNull Pair, Map> pairOfVariableStatusMap) { + pseudocodeData = data; + this.instruction = instruction; + + for (Map.Entry entry : pairOfVariableInitializersMap.second.entrySet()) { + VariableDescriptor variableDescriptor = entry.getKey(); + VariableInitializers in = pairOfVariableInitializersMap.first.get(variableDescriptor); + VariableInitializers out = entry.getValue(); + initializersMap.put(variableDescriptor, EdgesData.create(in, out)); + } + + for (Map.Entry entry : pairOfVariableStatusMap.second.entrySet()) { + VariableDescriptor variableDescriptor = entry.getKey(); + VariableUseStatus in = pairOfVariableStatusMap.first.get(variableDescriptor); + VariableUseStatus out = entry.getValue(); + if (in == null || out == null) continue; + useStatusMap.put(variableDescriptor, EdgesData.create(in, out)); + } + } + + @NotNull + public Map> getInitializersMap() { + return initializersMap; + } + + @NotNull + public Map> getUseStatusMap() { + return useStatusMap; + } + + public static class EdgesData { + private final T in; + private final T out; + + private EdgesData(@NotNull T in, @NotNull T out) { + this.in = in; + this.out = out; + } + + private static EdgesData create(@NotNull T in, @NotNull T out) { + return new EdgesData(in, out); + } + + @NotNull + public T getIn() { + return in; + } + + @NotNull + public T getOut() { + return out; + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java new file mode 100644 index 00000000000..d78011e47a4 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java @@ -0,0 +1,331 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.JetControlFlowGraphTraverser; +import org.jetbrains.jet.lang.cfg.pseudocode.*; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetProperty; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.BindingTrace; + +import java.util.*; + +/** + * @author svtk + */ +public class PseudocodeData { + private final Pseudocode pseudocode; + private final Map instructionDataMap = Maps.newLinkedHashMap(); + private final Map declarationDataMap = Maps.newLinkedHashMap(); + private final BindingTrace trace; + + public PseudocodeData(@NotNull Pseudocode pseudocode, @NotNull BindingTrace trace) { + this.pseudocode = pseudocode; + this.trace = trace; + collectDeclarationData(pseudocode); + + DeclarationData declarationData = declarationDataMap.get(pseudocode); + + final Map, Map>> variableInitializersMap = + collectVariableInitializers(pseudocode, declarationData); + final Map, Map>> variableStatusMap = + collectVariableStatusData(); + + JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph( + new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { + @Override + public void execute(@NotNull Instruction instruction, Void enterData, Void exitData) { + instructionDataMap.put(instruction, + new InstructionData(PseudocodeData.this, instruction, variableInitializersMap.get(instruction), + variableStatusMap.get(instruction))); + } + }); + } + + @NotNull + public Pseudocode getPseudocode() { + return pseudocode; + } + + @NotNull + public Map getInstructionDataMap() { + return instructionDataMap; + } + + @NotNull + public DeclarationData getDeclarationData(Pseudocode pseudocode) { + return declarationDataMap.get(pseudocode); + } + + @NotNull + public InstructionData getResultInfo(Pseudocode pseudocode) { + return instructionDataMap.get(pseudocode.getExitInstruction()); + } + + public void traverseInstructionsGraph(boolean lookInside, boolean straightDirection, + @NotNull TraverseInstructionGraphStrategy traverseInstructionGraphStrategy) { + traverseInstructionsGraph(pseudocode, lookInside, straightDirection, traverseInstructionGraphStrategy); + } + + private void traverseInstructionsGraph(@NotNull Pseudocode pseudocode, + boolean lookInside, + boolean straightDirection, + @NotNull TraverseInstructionGraphStrategy traverseInstructionGraphStrategy) { + List instructions = pseudocode.getInstructions(); + if (!straightDirection) { + instructions = Lists.newArrayList(instructions); + Collections.reverse(instructions); + } + for (Instruction instruction : instructions) { + if (lookInside && instruction instanceof LocalDeclarationInstruction) { + traverseInstructionsGraph(((LocalDeclarationInstruction) instruction).getBody(), lookInside, straightDirection, + traverseInstructionGraphStrategy + ); + } + traverseInstructionGraphStrategy.execute(instruction, declarationDataMap.get(pseudocode), instructionDataMap.get(instruction)); + } + } + + public interface TraverseInstructionGraphStrategy { + void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData); + } + + private void collectDeclarationData(Pseudocode pseudocode) { + DeclarationData declarationData = new DeclarationData(pseudocode.getCorrespondingElement(), this, collectDeclaredVariables(pseudocode), collectUsedVariables(pseudocode)); + declarationDataMap.put(pseudocode, declarationData); + + for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + collectDeclarationData(localPseudocode); + } + } + + private Set collectUsedVariables(@NotNull Pseudocode pseudocode) { + final Set usedVariables = Sets.newHashSet(); + JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { + @Override + public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { + VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); + if (variableDescriptor != null) { + usedVariables.add(variableDescriptor); + } + } + }); + return usedVariables; + } + + private Set collectDeclaredVariables(@NotNull Pseudocode pseudocode) { + final Set declaredVariables = Sets.newHashSet(); + JetControlFlowGraphTraverser.create(pseudocode, false, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { + @Override + public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { + if (instruction instanceof VariableDeclarationInstruction) { + JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement); + if (descriptor != null) { + assert descriptor instanceof VariableDescriptor; + declaredVariables.add((VariableDescriptor) descriptor); + } + } + } + }); + return declaredVariables; + } + +// variable initializers + + private Map, Map>> collectVariableInitializers( + Pseudocode pseudocode, DeclarationData data) { + + JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, false, true); + + final Map initialMapForStartInstruction = prepareInitialMapForStartInstruction(data.usedVariables, data.declaredVariables); + + traverser.collectInformationFromInstructionGraph(Collections.emptyMap(), initialMapForStartInstruction, + new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { + @Override + public Pair, Map> execute( + @NotNull Instruction instruction, + @NotNull Collection> incomingEdgesData) { + + Map enterInstructionData = mergeIncomingEdgesData(incomingEdgesData); + Map exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); + return Pair.create(enterInstructionData, exitInstructionData); + } + }); + + Map, Map>> result = + traverser.getDataMap(); + for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + Map, Map>> initializersForLocalDeclaration = + collectVariableInitializers(localPseudocode, declarationDataMap.get(localPseudocode)); + + for (Instruction instruction : initializersForLocalDeclaration.keySet()) { + //todo + if (!result.containsKey(instruction)) { + result.put(instruction, initializersForLocalDeclaration.get(instruction)); + } + } + result.putAll(initializersForLocalDeclaration); + } + + return result; + } + + private Map prepareInitialMapForStartInstruction(Collection usedVariables, Collection declaredVariables) { + Map initialMapForStartInstruction = Maps.newHashMap(); + VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true); + VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false); + + for (VariableDescriptor variable : usedVariables) { + if (declaredVariables.contains(variable)) { + initialMapForStartInstruction.put(variable, isNotInitializedForDeclaredVariable); + } + else { + initialMapForStartInstruction.put(variable, isInitializedForExternalVariable); + } + } + return initialMapForStartInstruction; + } + + private Map mergeIncomingEdgesData(Collection> incomingEdgesData) { + Set variablesInScope = Sets.newHashSet(); + for (Map edgeData : incomingEdgesData) { + variablesInScope.addAll(edgeData.keySet()); + } + + Map enterInstructionData = Maps.newHashMap(); + for (VariableDescriptor variable : variablesInScope) { + Set edgesDataForVariable = Sets.newHashSet(); + for (Map edgeData : incomingEdgesData) { + VariableInitializers initializers = edgeData.get(variable); + if (initializers != null) { + edgesDataForVariable.add(initializers); + } + } + enterInstructionData.put(variable, new VariableInitializers(edgesDataForVariable)); + } + return enterInstructionData; + } + + private Map addVariableInitializerFromCurrentInstructionIfAny(Instruction instruction, Map enterInstructionData) { + if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) { + return enterInstructionData; + } + VariableDescriptor variable = extractVariableDescriptorIfAny(instruction, false); + if (variable == null) { + return enterInstructionData; + } + Map exitInstructionData = Maps.newHashMap(enterInstructionData); + if (instruction instanceof WriteValueInstruction) { + VariableInitializers enterInitializers = enterInstructionData.get(variable); + VariableInitializers initializationAtThisElement = new VariableInitializers(((WriteValueInstruction) instruction).getElement(), enterInitializers); + exitInstructionData.put(variable, initializationAtThisElement); + } + else { + VariableInitializers enterInitializers = enterInstructionData.get(variable); + if (enterInitializers == null || !enterInitializers.isInitialized() || !enterInitializers.isDeclared()) { + JetElement element = ((VariableDeclarationInstruction) instruction).getElement(); + if (element instanceof JetProperty) { + JetProperty property = (JetProperty) element; + if (property.getInitializer() == null) { + boolean isInitialized = enterInitializers != null && enterInitializers.isInitialized(); + VariableInitializers variableDeclarationInfo = new VariableInitializers(isInitialized, true); + exitInstructionData.put(variable, variableDeclarationInfo); + } + } + } + } + return exitInstructionData; + } + +// variable use + + private Map, Map>> collectVariableStatusData() { + JetControlFlowGraphTraverser> traverser = + JetControlFlowGraphTraverser.create(pseudocode, true, false); + Map sinkInstructionData = Maps.newHashMap(); + for (VariableDescriptor usedVariable : declarationDataMap.get(pseudocode).usedVariables) { + sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); + } + traverser.collectInformationFromInstructionGraph(Collections.emptyMap(), sinkInstructionData, + new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { + @Override + public Pair, Map> execute(@NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { + Map enterResult = Maps.newHashMap(); + for (Map edgeData : incomingEdgesData) { + for (Map.Entry entry : edgeData.entrySet()) { + VariableDescriptor variableDescriptor = entry.getKey(); + VariableUseStatus variableUseStatus = entry.getValue(); + enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor))); + } + } + VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); + if (variableDescriptor == null || (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) { + return Pair.create(enterResult, enterResult); + } + Map exitResult = Maps.newHashMap(enterResult); + if (instruction instanceof ReadValueInstruction) { + exitResult.put(variableDescriptor, VariableUseStatus.LAST_READ); + } + else { + VariableUseStatus variableUseStatus = enterResult.get(variableDescriptor); + if (variableUseStatus == null) variableUseStatus = VariableUseStatus.UNUSED; + switch (variableUseStatus) { + case UNUSED: + case ONLY_WRITTEN_NEVER_READ: + exitResult.put(variableDescriptor, VariableUseStatus.ONLY_WRITTEN_NEVER_READ); + break; + case LAST_WRITTEN: + case LAST_READ: + exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN); + } + } + return Pair.create(enterResult, exitResult); + } + }); + return traverser.getDataMap(); + } + +// Util methods + + @Nullable + public VariableDescriptor extractVariableDescriptorIfAny(@NotNull Instruction instruction, boolean onlyReference) { + JetElement element = null; + if (instruction instanceof ReadValueInstruction) { + element = ((ReadValueInstruction) instruction).getElement(); + } + else if (instruction instanceof WriteValueInstruction) { + element = ((WriteValueInstruction) instruction).getlValue(); + } + else if (instruction instanceof VariableDeclarationInstruction) { + element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + } + return BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), element, onlyReference); + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java new file mode 100644 index 00000000000..c30cef1a60f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; + +import com.google.common.collect.Sets; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetProperty; + +import java.util.Set; + +/** +* @author svtk +*/ +public class VariableInitializers { + private final Set possibleLocalInitializers = Sets.newHashSet(); + private boolean isInitialized; + private boolean isDeclared; + + public VariableInitializers(boolean isInitialized) { + this(isInitialized, false); + } + + public VariableInitializers(boolean isInitialized, boolean isDeclared) { + this.isInitialized = isInitialized; + this.isDeclared = isDeclared; + } + + public VariableInitializers(JetElement element, @Nullable VariableInitializers previous) { + isInitialized = true; + isDeclared = element instanceof JetProperty || (previous != null && previous.isDeclared()); + possibleLocalInitializers.add(element); + } + + public VariableInitializers(Set edgesData) { + isInitialized = true; + isDeclared = true; + for (VariableInitializers edgeData : edgesData) { + if (!edgeData.isInitialized) { + isInitialized = false; + } + if (!edgeData.isDeclared) { + isDeclared = false; + } + possibleLocalInitializers.addAll(edgeData.possibleLocalInitializers); + } + } + + public Set getPossibleLocalInitializers() { + return possibleLocalInitializers; + } + + public boolean isInitialized() { + return isInitialized; + } + + public boolean isDeclared() { + return isDeclared; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof VariableInitializers)) return false; + + VariableInitializers that = (VariableInitializers) o; + + if (isDeclared != that.isDeclared) return false; + if (isInitialized != that.isInitialized) return false; + if (possibleLocalInitializers != null + ? !possibleLocalInitializers.equals(that.possibleLocalInitializers) + : that.possibleLocalInitializers != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = possibleLocalInitializers != null ? possibleLocalInitializers.hashCode() : 0; + result = 31 * result + (isInitialized ? 1 : 0); + result = 31 * result + (isDeclared ? 1 : 0); + return result; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java new file mode 100644 index 00000000000..0d1b6bb7a9e --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; + +import org.jetbrains.annotations.Nullable; + +/** +* @author svtk +*/ +public enum VariableUseStatus { + LAST_READ(3), + LAST_WRITTEN(2), + ONLY_WRITTEN_NEVER_READ(1), + UNUSED(0); + + private final int importance; + + VariableUseStatus(int importance) { + this.importance = importance; + } + + public VariableUseStatus merge(@Nullable VariableUseStatus variableUseStatus) { + if (variableUseStatus == null || importance > variableUseStatus.importance) return this; + return variableUseStatus; + } +} From 5c7b787e688d6607192ffa9bb1a3148e710858ed Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 25 May 2012 21:07:33 +0400 Subject: [PATCH 02/24] reversed traverse in depth --- .../cfg/JetControlFlowGraphTraverser.java | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java index bf42c3ec570..7fd6e252c82 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -24,10 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.pseudocode.*; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author svtk @@ -53,6 +50,11 @@ public class JetControlFlowGraphTraverser { return straightDirection ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } + @NotNull + public Map> getDataMap() { + return dataMap; + } + public void collectInformationFromInstructionGraph( @NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction, @@ -82,6 +84,22 @@ public class JetControlFlowGraphTraverser { } } + private static List reverseInstructions(@NotNull Pseudocode pseudocode) { + LinkedHashSet traversedInstructions = Sets.newLinkedHashSet(); + Instruction sinkInstruction = pseudocode.getSinkInstruction(); + traverseInstructions(sinkInstruction, traversedInstructions); + return Lists.newArrayList(traversedInstructions); + } + + private static void traverseInstructions(@NotNull Instruction instruction, @NotNull LinkedHashSet instructions) { + if (((InstructionImpl)instruction).isDead()) return; + if (instructions.contains(instruction)) return; + instructions.add(instruction); + for (Instruction previousInstruction : instruction.getPreviousInstructions()) { + traverseInstructions(previousInstruction, instructions); + } + } + private void traverseSubGraph( @NotNull Pseudocode pseudocode, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, @@ -92,8 +110,7 @@ public class JetControlFlowGraphTraverser { Instruction startInstruction = getStartInstruction(pseudocode); if (!straightDirection) { - instructions = Lists.newArrayList(instructions); - Collections.reverse(instructions); + instructions = reverseInstructions(pseudocode); } for (Instruction instruction : instructions) { boolean isStart = straightDirection ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; @@ -170,11 +187,11 @@ public class JetControlFlowGraphTraverser { return dataMap.get(pseudocode.getExitInstruction()).getFirst(); } - interface InstructionDataMergeStrategy { + public interface InstructionDataMergeStrategy { Pair execute(@NotNull Instruction instruction, @NotNull Collection incomingEdgesData); } - interface InstructionDataAnalyzeStrategy { + public interface InstructionDataAnalyzeStrategy { void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData); } } From edb529f68fc0b741f22d208fcb2fe8b3225e447e Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 25 May 2012 21:18:00 +0400 Subject: [PATCH 03/24] added edge 'error' -> 'sink' added 'getLocalDeclarations' method to pseudocode --- .../jet/lang/cfg/pseudocode/Pseudocode.java | 20 +++-- .../pseudocode/SubroutineExitInstruction.java | 6 +- .../cfg/AnonymousInitializers.instructions | 12 +-- .../testData/cfg/ArrayAccess.instructions | 4 +- .../testData/cfg/Assignments.instructions | 8 +- compiler/testData/cfg/Basic.instructions | 24 +++--- .../testData/cfg/EmptyFunction.instructions | 4 +- .../testData/cfg/FailFunction.instructions | 4 +- compiler/testData/cfg/Finally.instructions | 84 +++++++++---------- compiler/testData/cfg/For.instructions | 8 +- compiler/testData/cfg/If.instructions | 12 +-- .../testData/cfg/LazyBooleans.instructions | 4 +- .../cfg/LocalDeclarations.instructions | 72 ++++++++-------- .../cfg/OnlyWhileInFunctionBody.instructions | 8 +- .../cfg/ReturnFromExpression.instructions | 4 +- .../testData/cfg/ShortFunction.instructions | 4 +- 16 files changed, 143 insertions(+), 135 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index 47dcbea39ea..1c5303de8fe 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -17,16 +17,14 @@ package org.jetbrains.jet.lang.cfg.pseudocode; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.Label; import org.jetbrains.jet.lang.psi.JetElement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author abreslav @@ -95,6 +93,17 @@ public class Pseudocode { return correspondingElement; } + public Set getLocalDeclarations() { + Set localDeclarations = Sets.newLinkedHashSet(); + //todo look recursively inside local declarations + for (Instruction instruction : instructions) { + if (instruction instanceof LocalDeclarationInstruction) { + localDeclarations.add(((LocalDeclarationInstruction) instruction).getBody()); + } + } + return localDeclarations; + } + public PseudocodeLabel createLabel(String name) { PseudocodeLabel label = new PseudocodeLabel(name); labels.add(label); @@ -190,10 +199,11 @@ public class Pseudocode { public void postProcess() { if (postPrecessed) return; postPrecessed = true; + errorInstruction.setSink(getSinkInstruction()); + exitInstruction.setSink(getSinkInstruction()); for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) { processInstruction(mutableInstructionList.get(i), i); } - getExitInstruction().setSink(getSinkInstruction()); Set reachableInstructions = collectReachableInstructions(); for (Instruction instruction : mutableInstructionList) { if (reachableInstructions.contains(instruction)) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/SubroutineExitInstruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/SubroutineExitInstruction.java index 1e9f26d81f1..c3ad2ee983f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/SubroutineExitInstruction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/SubroutineExitInstruction.java @@ -46,10 +46,8 @@ public class SubroutineExitInstruction extends InstructionImpl { @NotNull @Override public Collection getNextInstructions() { - if (sinkInstruction != null) { - return Collections.singleton(sinkInstruction); - } - return Collections.emptyList(); + assert sinkInstruction != null; + return Collections.singleton(sinkInstruction); } @Override diff --git a/compiler/testData/cfg/AnonymousInitializers.instructions b/compiler/testData/cfg/AnonymousInitializers.instructions index 4636a66a836..32d8f65e3a2 100644 --- a/compiler/testData/cfg/AnonymousInitializers.instructions +++ b/compiler/testData/cfg/AnonymousInitializers.instructions @@ -7,9 +7,9 @@ l0: l1: NEXT:[] PREV:[r(20)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == AnonymousInitializers == class AnonymousInitializers() { @@ -46,16 +46,16 @@ l2: l1: NEXT:[] PREV:[w($i)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[d(get() = 20), ] + NEXT:[] PREV:[, , d(get() = 20)] l3: NEXT:[r(20)] PREV:[] r(20) NEXT:[] PREV:[] l4: NEXT:[] PREV:[r(20)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/ArrayAccess.instructions b/compiler/testData/cfg/ArrayAccess.instructions index 6bdc275b8e8..1e0e143d1de 100644 --- a/compiler/testData/cfg/ArrayAccess.instructions +++ b/compiler/testData/cfg/ArrayAccess.instructions @@ -35,7 +35,7 @@ l0: l1: NEXT:[] PREV:[w(a[10])] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/Assignments.instructions b/compiler/testData/cfg/Assignments.instructions index ec20a1a74fa..dc70c8556fb 100644 --- a/compiler/testData/cfg/Assignments.instructions +++ b/compiler/testData/cfg/Assignments.instructions @@ -9,9 +9,9 @@ l0: l1: NEXT:[] PREV:[v(var x : Int;)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == assignments == fun assignments() : Unit { @@ -72,7 +72,7 @@ l5: l1: NEXT:[] PREV:[w(t.x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/Basic.instructions b/compiler/testData/cfg/Basic.instructions index cfe03b78040..abd49b300ab 100644 --- a/compiler/testData/cfg/Basic.instructions +++ b/compiler/testData/cfg/Basic.instructions @@ -7,9 +7,9 @@ l3: l4: NEXT:[] PREV:[r(1)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == f == fun f(a : Boolean) : Unit { @@ -78,18 +78,18 @@ l6: l1: NEXT:[] PREV:[r(a || false)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[d({1}), ] + NEXT:[] PREV:[, , d({1})] l3: NEXT:[r(1)] PREV:[] r(1) NEXT:[] PREV:[] l4: NEXT:[] PREV:[r(1)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == foo == fun foo(a : Boolean, b : Int) : Unit {} @@ -104,9 +104,9 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == genfun == fun genfun() : Unit {} @@ -117,9 +117,9 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == flfun == fun flfun(f : () -> Any) : Unit {} @@ -132,7 +132,7 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/EmptyFunction.instructions b/compiler/testData/cfg/EmptyFunction.instructions index b7afe8758e2..054789e37c6 100644 --- a/compiler/testData/cfg/EmptyFunction.instructions +++ b/compiler/testData/cfg/EmptyFunction.instructions @@ -7,7 +7,7 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/FailFunction.instructions b/compiler/testData/cfg/FailFunction.instructions index be84d56dee9..c8a3ab1c608 100644 --- a/compiler/testData/cfg/FailFunction.instructions +++ b/compiler/testData/cfg/FailFunction.instructions @@ -15,7 +15,7 @@ l0: l1: NEXT:[] PREV:[] error: - NEXT:[] PREV:[jmp(error)] + NEXT:[] PREV:[jmp(error)] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/Finally.instructions b/compiler/testData/cfg/Finally.instructions index 140aa447092..d9ef32e086e 100644 --- a/compiler/testData/cfg/Finally.instructions +++ b/compiler/testData/cfg/Finally.instructions @@ -21,9 +21,9 @@ l1: l3: NEXT:[] PREV:[r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t2 == fun t2() { @@ -65,9 +65,9 @@ l1: l5: NEXT:[] PREV:[ret l1, r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == anonymous_0 == { () => @@ -92,9 +92,9 @@ l4: l6: NEXT:[] PREV:[ret l4, read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t3 == fun t3() { @@ -141,9 +141,9 @@ l1: l8: NEXT:[] PREV:[r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[d({ () => if (2 > 3) { retur..), ] + NEXT:[] PREV:[, , d({ () => if (2 > 3) { retur..)] l3: NEXT:[r(())] PREV:[] r(()) NEXT:[r(2)] PREV:[] @@ -160,9 +160,9 @@ l4: l6: NEXT:[] PREV:[ret l4, read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == anonymous_1 == { () => @@ -205,9 +205,9 @@ l4: l8: NEXT:[] PREV:[ret l4, r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t4 == fun t4() { @@ -250,9 +250,9 @@ l2: l1: NEXT:[] PREV:[r({ () => try { 1 if (2 > 3)..)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[d({ () => try { 1 if (2 > 3)..), ] + NEXT:[] PREV:[, , d({ () => try { 1 if (2 > 3)..)] l3: NEXT:[r(())] PREV:[] r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[] @@ -282,9 +282,9 @@ l4: l8: NEXT:[] PREV:[ret l4, r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t5 == fun t5() { @@ -346,9 +346,9 @@ l3: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t6 == fun t6() { @@ -410,9 +410,9 @@ l1: l9: NEXT:[] PREV:[r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t7 == fun t7() { @@ -471,9 +471,9 @@ l1: l9: NEXT:[] PREV:[r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t8 == fun t8(a : Int) { @@ -542,9 +542,9 @@ l2: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t9 == fun t9(a : Int) { @@ -613,9 +613,9 @@ l1: l9: NEXT:[] PREV:[r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t10 == fun t10(a : Int) { @@ -681,9 +681,9 @@ l1: l9: NEXT:[] PREV:[r(2)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t11 == fun t11() { @@ -714,9 +714,9 @@ l1: l3: NEXT:[] PREV:[ret(*) l1] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t12 == fun t12() : Int { @@ -749,9 +749,9 @@ l1: l3: NEXT:[] PREV:[ret(*) l1] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t13 == fun t13() : Int { @@ -802,9 +802,9 @@ l1: l6: NEXT:[] PREV:[ret(*) l1, r(doSmth(3))] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t14 == fun t14() : Int { @@ -843,9 +843,9 @@ l4: l6: NEXT:[] PREV:[ret(*) l1, jmp(l4)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t15 == fun t15() : Int { @@ -898,9 +898,9 @@ l1: l6: NEXT:[] PREV:[ret(*) l1, ret(*) l1] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t16 == fun t16() : Int { @@ -951,9 +951,9 @@ l1: l6: NEXT:[] PREV:[ret(*) l1, r(doSmth(3))] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == doSmth == fun doSmth(i: Int) { @@ -967,7 +967,7 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/For.instructions b/compiler/testData/cfg/For.instructions index 9361d5f5882..f0935934a8b 100644 --- a/compiler/testData/cfg/For.instructions +++ b/compiler/testData/cfg/For.instructions @@ -29,9 +29,9 @@ l2: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == doSmth == fun doSmth(i: Int) {} @@ -44,7 +44,7 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/If.instructions b/compiler/testData/cfg/If.instructions index 1a035099610..f23eeeeacd8 100644 --- a/compiler/testData/cfg/If.instructions +++ b/compiler/testData/cfg/If.instructions @@ -48,9 +48,9 @@ l5: l1: NEXT:[] PREV:[r(doSmth(r))] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == t2 == fun t2(b: Boolean) { @@ -92,9 +92,9 @@ l1: l5: NEXT:[] PREV:[ret l1, ret l1, read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == doSmth == fun doSmth(s: String) {} @@ -107,7 +107,7 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/LazyBooleans.instructions b/compiler/testData/cfg/LazyBooleans.instructions index f204026d0a0..0fd8ee339c4 100644 --- a/compiler/testData/cfg/LazyBooleans.instructions +++ b/compiler/testData/cfg/LazyBooleans.instructions @@ -72,7 +72,7 @@ l13: l1: NEXT:[] PREV:[r(14)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/LocalDeclarations.instructions b/compiler/testData/cfg/LocalDeclarations.instructions index 060b9e31931..500f605b982 100644 --- a/compiler/testData/cfg/LocalDeclarations.instructions +++ b/compiler/testData/cfg/LocalDeclarations.instructions @@ -25,9 +25,9 @@ l0: l1: NEXT:[] PREV:[w(a)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == O == object O { @@ -45,9 +45,9 @@ l0: l1: NEXT:[] PREV:[w($x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == null == object { @@ -72,9 +72,9 @@ l0: l1: NEXT:[] PREV:[w($x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == doSmth == fun doSmth(i: Int) {} @@ -87,9 +87,9 @@ l0: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == test1 == fun test1() { @@ -122,9 +122,9 @@ l0: l1: NEXT:[] PREV:[w(a)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == test2 == fun test2() { @@ -152,9 +152,9 @@ l0: l1: NEXT:[] PREV:[w(a)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == inner_bar == fun inner_bar() { @@ -168,9 +168,9 @@ l3: l4: NEXT:[] PREV:[w(y)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == test3 == fun test3() { @@ -206,9 +206,9 @@ l2: l1: NEXT:[] PREV:[w(a)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[d(fun inner_bar() { y = 10 }) , ] + NEXT:[] PREV:[, , d(fun inner_bar() { y = 10 }) ] l3: NEXT:[r(10)] PREV:[] r(10) NEXT:[w(y)] PREV:[] @@ -216,9 +216,9 @@ l3: l4: NEXT:[] PREV:[w(y)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == ggg == fun ggg() { @@ -232,9 +232,9 @@ l3: l4: NEXT:[] PREV:[w(y)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == test4 == fun test4() { @@ -285,9 +285,9 @@ l2: l1: NEXT:[] PREV:[w(a)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[d(fun ggg() { y = 10 }) , ] + NEXT:[] PREV:[, , d(fun ggg() { y = 10 }) ] l3: NEXT:[r(10)] PREV:[] r(10) NEXT:[w(y)] PREV:[] @@ -295,9 +295,9 @@ l3: l4: NEXT:[] PREV:[w(y)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == foo == fun foo() { @@ -311,9 +311,9 @@ l3: l4: NEXT:[] PREV:[w(x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == bar == fun bar() { @@ -327,9 +327,9 @@ l6: l7: NEXT:[] PREV:[w(x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == test5 == fun test5() { @@ -392,9 +392,9 @@ l5: l1: NEXT:[] PREV:[w(a)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[d(fun foo() { x = 3 }) , d(fun bar() { x = 4 }) , ] + NEXT:[] PREV:[, , d(fun foo() { x = 3 }) , d(fun bar() { x = 4 }) ] l3: NEXT:[r(3)] PREV:[] r(3) NEXT:[w(x)] PREV:[] @@ -402,9 +402,9 @@ l3: l4: NEXT:[] PREV:[w(x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] l6: NEXT:[r(4)] PREV:[] r(4) NEXT:[w(x)] PREV:[] @@ -412,9 +412,9 @@ l6: l7: NEXT:[] PREV:[w(x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == foo == fun foo() { @@ -433,7 +433,7 @@ l0: l1: NEXT:[] PREV:[r(doSmth(b))] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/OnlyWhileInFunctionBody.instructions b/compiler/testData/cfg/OnlyWhileInFunctionBody.instructions index 800e16ea283..9d51f4a9e6a 100644 --- a/compiler/testData/cfg/OnlyWhileInFunctionBody.instructions +++ b/compiler/testData/cfg/OnlyWhileInFunctionBody.instructions @@ -25,9 +25,9 @@ l3: l1: NEXT:[] PREV:[read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== == dowhile == fun dowhile() { @@ -53,7 +53,7 @@ l3: l1: NEXT:[] PREV:[ret l1] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/ReturnFromExpression.instructions b/compiler/testData/cfg/ReturnFromExpression.instructions index 42171bf2a21..be7801a3b2a 100644 --- a/compiler/testData/cfg/ReturnFromExpression.instructions +++ b/compiler/testData/cfg/ReturnFromExpression.instructions @@ -15,7 +15,7 @@ l2: l1: NEXT:[] PREV:[ret(*) l1, r(false || (return false))] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== diff --git a/compiler/testData/cfg/ShortFunction.instructions b/compiler/testData/cfg/ShortFunction.instructions index fa0b7bbd2fe..138afba140a 100644 --- a/compiler/testData/cfg/ShortFunction.instructions +++ b/compiler/testData/cfg/ShortFunction.instructions @@ -7,7 +7,7 @@ l0: l1: NEXT:[] PREV:[r(1)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[] + NEXT:[] PREV:[, ] ===================== From b6b1ce52e1e49da1740c750500a5502844181589 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 25 May 2012 21:18:55 +0400 Subject: [PATCH 04/24] tests changed: added check for unused/uninitialized variables inside local and anonymous functions --- .../diagnostics/tests/FunctionReturnTypes.jet | 16 ++++++++-------- .../diagnostics/tests/StringTemplates.jet | 6 +++--- .../tests/UninitializedOrReassignedVariables.jet | 6 +++--- .../diagnostics/tests/regressions/kt235.jet | 6 +++--- .../ShadowParameterInNestedBlockInFor.jet | 4 ++-- .../shadowing/ShadowVariableInNestedBlock.jet | 4 ++-- .../shadowing/ShadowVariableInNestedClosure.jet | 4 ++-- idea/testData/checker/StringTemplates.jet | 4 ++-- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet b/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet index 5202b74ec61..7374b73bd99 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet @@ -175,12 +175,12 @@ class B() { fun testFunctionLiterals() { val endsWithVarDeclaration : () -> Boolean = { - val x = 2 + val x = 2 } val endsWithAssignment = { () : Int -> - var x = 1 - x = 333 + var x = 1 + x = 333 } val endsWithReAssignment = { () : Int -> @@ -189,19 +189,19 @@ fun testFunctionLiterals() { } val endsWithFunDeclaration : () -> String = { - var x = 1 - x = 333 + var x = 1 + x = 333 fun meow() : Unit {} } val endsWithObjectDeclaration : () -> Int = { - var x = 1 - x = 333 + var x = 1 + x = 333 object A {} } val expectedUnitReturnType1 = { () : Unit -> - val x = 1 + val x = 1 } val expectedUnitReturnType2 = { () : Unit -> diff --git a/compiler/testData/diagnostics/tests/StringTemplates.jet b/compiler/testData/diagnostics/tests/StringTemplates.jet index 7c0d90f20be..15bb94259ec 100644 --- a/compiler/testData/diagnostics/tests/StringTemplates.jet +++ b/compiler/testData/diagnostics/tests/StringTemplates.jet @@ -3,8 +3,8 @@ fun demo() { val a = "" val asd = 1 val bar = 5 - fun map(f : () -> Any?) : Int = 1 - fun buzz(f : () -> Any?) : Int = 1 + fun map(f : () -> Any?) : Int = 1 + fun buzz(f : () -> Any?) : Int = 1 val sdf = 1 val foo = 3; "$abc" @@ -19,4 +19,4 @@ fun demo() { "foo${bar + map { "foo$sdf${ buzz{}}" }}sdfsdf" "a\u \u0 \u00 \u000 \u0000 \u0AaA \u0AAz.length( ) + \u0022b" -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/UninitializedOrReassignedVariables.jet b/compiler/testData/diagnostics/tests/UninitializedOrReassignedVariables.jet index 27be26f068d..e76d907ce23 100644 --- a/compiler/testData/diagnostics/tests/UninitializedOrReassignedVariables.jet +++ b/compiler/testData/diagnostics/tests/UninitializedOrReassignedVariables.jet @@ -101,7 +101,7 @@ fun t5() { for (i in 0..2) { i += 1 fun t5() { - i += 3 + i += 3 } } } @@ -297,8 +297,8 @@ class TestObjectExpression() { a = 231 } fun inner2() { - y = 101 - a = 231 + y = 101 + a = 231 } } } diff --git a/compiler/testData/diagnostics/tests/regressions/kt235.jet b/compiler/testData/diagnostics/tests/regressions/kt235.jet index 5d86407e32e..5adfcf6adbc 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt235.jet +++ b/compiler/testData/diagnostics/tests/regressions/kt235.jet @@ -12,8 +12,8 @@ fun main(args: Array) { x += 2 //no error, but it should be here } val h = {(): String -> - var x = 1 - x = 2 //the same + var x = 1 + x = 2 //the same } val array1 = MyArray1() val i = { (): String -> @@ -46,4 +46,4 @@ class MyArray1() { class MyNumber() { fun inc(): MyNumber = MyNumber() -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/shadowing/ShadowParameterInNestedBlockInFor.jet b/compiler/testData/diagnostics/tests/shadowing/ShadowParameterInNestedBlockInFor.jet index e9534b0cf26..8d11904199a 100644 --- a/compiler/testData/diagnostics/tests/shadowing/ShadowParameterInNestedBlockInFor.jet +++ b/compiler/testData/diagnostics/tests/shadowing/ShadowParameterInNestedBlockInFor.jet @@ -1,7 +1,7 @@ fun f(i: Int) { for (j in 1..100) { { - var i = 12 + var i = 12 } } -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedBlock.jet b/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedBlock.jet index ac5ff05e1f5..815357015d2 100644 --- a/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedBlock.jet +++ b/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedBlock.jet @@ -1,7 +1,7 @@ fun ff(): Int { var i = 1 { - val i = 2 + val i = 2 } return i -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedClosure.jet b/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedClosure.jet index b64caacd881..29ebe8f2c2e 100644 --- a/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedClosure.jet +++ b/compiler/testData/diagnostics/tests/shadowing/ShadowVariableInNestedClosure.jet @@ -1,5 +1,5 @@ fun f(): Int { var i = 17 - { (): Unit -> var i = 18 } + { (): Unit -> var i = 18 } return i -} +} \ No newline at end of file diff --git a/idea/testData/checker/StringTemplates.jet b/idea/testData/checker/StringTemplates.jet index 236c7a4f0ef..88cd788a1ad 100644 --- a/idea/testData/checker/StringTemplates.jet +++ b/idea/testData/checker/StringTemplates.jet @@ -3,8 +3,8 @@ fun demo() { val a = "" val asd = 1 val bar = 5 - fun map(f : () -> Any?) : Int = 1 - fun buzz(f : () -> Any?) : Int = 1 + fun map(f : () -> Any?) : Int = 1 + fun buzz(f : () -> Any?) : Int = 1 val sdf = 1 val foo = 3; use("$abc") From f4920b7d0990fcd6b315bf2843bbb7a7046d8d66 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 12:42:06 +0400 Subject: [PATCH 05/24] added 'Pseudocode' interface 'Pseudocode' class was renamed to 'PseudocodeImpl' --- .../jet/lang/cfg/pseudocode/IPseudocode.java | 49 +++++++++++++++++++ .../{Pseudocode.java => PseudocodeImpl.java} | 37 +++++++++++--- 2 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/IPseudocode.java rename compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/{Pseudocode.java => PseudocodeImpl.java} (92%) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/IPseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/IPseudocode.java new file mode 100644 index 00000000000..55f2d54570d --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/IPseudocode.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.pseudocode; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetElement; + +import java.util.List; +import java.util.Set; + +/** + * @author svtk + */ +public interface IPseudocode { + @NotNull + JetElement getCorrespondingElement(); + + @NotNull + Set getLocalDeclarations(); + + @NotNull + List getInstructions(); + + @NotNull + List getDeadInstructions(); + + @NotNull + SubroutineExitInstruction getExitInstruction(); + + @NotNull + SubroutineSinkInstruction getSinkInstruction(); + + @NotNull + SubroutineEnterInstruction getEnterInstruction(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java similarity index 92% rename from compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java rename to compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index 1c5303de8fe..bac83677def 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -22,14 +22,17 @@ import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.Label; +import org.jetbrains.jet.lang.cfg.LoopInfo; import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetExpression; import java.util.*; /** * @author abreslav +* @author svtk */ -public class Pseudocode { +public class PseudocodeImpl implements IPseudocode { public class PseudocodeLabel implements Label { private final String name; @@ -74,6 +77,9 @@ public class Pseudocode { private final List mutableInstructionList = new ArrayList(); private final List instructions = new ArrayList(); private List deadInstructions; + + final Map representativeInstructions = new HashMap(); + final Map loopInfo = Maps.newHashMap(); private final List labels = new ArrayList(); private final List allowedDeadLabels = new ArrayList(); @@ -85,16 +91,20 @@ public class Pseudocode { private SubroutineExitInstruction errorInstruction; private boolean postPrecessed = false; - public Pseudocode(JetElement correspondingElement) { + public PseudocodeImpl(JetElement correspondingElement) { this.correspondingElement = correspondingElement; } + @NotNull + @Override public JetElement getCorrespondingElement() { return correspondingElement; } - public Set getLocalDeclarations() { - Set localDeclarations = Sets.newLinkedHashSet(); + @NotNull + @Override + public Set getLocalDeclarations() { + Set localDeclarations = Sets.newLinkedHashSet(); //todo look recursively inside local declarations for (Instruction instruction : instructions) { if (instruction instanceof LocalDeclarationInstruction) { @@ -118,6 +128,7 @@ public class Pseudocode { stopAllowDeadLabels.add((PseudocodeLabel) label); } + @Override @NotNull public List getInstructions() { return instructions; @@ -128,7 +139,8 @@ public class Pseudocode { public List getMutableInstructionList() { return mutableInstructionList; } - + + @Override @NotNull public List getDeadInstructions() { if (deadInstructions != null) { @@ -174,19 +186,30 @@ public class Pseudocode { public void addInstruction(Instruction instruction) { mutableInstructionList.add(instruction); instruction.setOwner(this); + + if (instruction instanceof JetElementInstruction) { + JetElementInstruction elementInstruction = (JetElementInstruction) instruction; + representativeInstructions.put(elementInstruction.getElement(), instruction); + } } + public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { + loopInfo.put(expression, blockInfo); + } + + @Override @NotNull public SubroutineExitInstruction getExitInstruction() { return exitInstruction; } + @Override @NotNull public SubroutineSinkInstruction getSinkInstruction() { return sinkInstruction; } - + @Override @NotNull public SubroutineEnterInstruction getEnterInstruction() { return (SubroutineEnterInstruction) mutableInstructionList.get(0); @@ -251,7 +274,7 @@ public class Pseudocode { @Override public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) { - instruction.getBody().postProcess(); + ((PseudocodeImpl)instruction.getBody()).postProcess(); instruction.setNext(getSinkInstruction()); } From 09a91f2f922af5cc884b3832e7d597ffb16dee0a Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 12:44:12 +0400 Subject: [PATCH 06/24] IPseudocode was a temporary name to deceive idea's git and commit it --- .../lang/cfg/pseudocode/{IPseudocode.java => Pseudocode.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/{IPseudocode.java => Pseudocode.java} (94%) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/IPseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java similarity index 94% rename from compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/IPseudocode.java rename to compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index 55f2d54570d..85d141b7e21 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/IPseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -25,12 +25,12 @@ import java.util.Set; /** * @author svtk */ -public interface IPseudocode { +public interface Pseudocode { @NotNull JetElement getCorrespondingElement(); @NotNull - Set getLocalDeclarations(); + Set getLocalDeclarations(); @NotNull List getInstructions(); From 0bf65bfe1e3a0c2eabac10ac5d4e87abfc80dd09 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 12:46:10 +0400 Subject: [PATCH 07/24] get rid of JetPseudocodeTrace and JetControlFlowDataTraceFactory --- .../compiler/KotlinToJVMBytecodeCompiler.java | 2 - .../jet/lang/cfg/JetControlFlowBuilder.java | 3 +- .../cfg/JetControlFlowBuilderAdapter.java | 5 +- .../jet/lang/cfg/JetControlFlowProcessor.java | 21 +++- .../lang/cfg/JetFlowInformationProvider.java | 101 ++++-------------- .../JetControlFlowDataTraceFactory.java | 36 ------- .../JetControlFlowInstructionsGenerator.java | 25 ++--- .../cfg/pseudocode/JetPseudocodeTrace.java | 54 ---------- .../lang/cfg/pseudocode/PseudocodeImpl.java | 6 +- .../jet/lang/resolve/AnalyzingUtils.java | 7 -- .../jet/lang/resolve/ControlFlowAnalyzer.java | 21 ++-- .../jet/lang/resolve/TopDownAnalyzer.java | 5 +- .../tests/org/jetbrains/jet/JetTestUtils.java | 5 +- .../jetbrains/jet/cfg/JetControlFlowTest.java | 72 ++++++++----- .../jet/checkers/CheckerTestUtilTest.java | 4 +- .../jet/checkers/JetDiagnosticsTest.java | 5 +- .../jvm/compiler/ReadJavaBinaryClassTest.java | 4 +- .../jet/codegen/CodegenTestCase.java | 4 +- .../jet/codegen/GenerationUtils.java | 4 +- .../jet/resolve/DescriptorRendererTest.java | 4 +- .../jet/resolve/ExpectedResolveData.java | 4 +- .../JetDefaultModalityModifiersTest.java | 2 - .../libraries/JetSourceNavigationHelper.java | 4 +- .../jet/di/AllInjectorsGenerator.java | 2 - 24 files changed, 118 insertions(+), 282 deletions(-) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowDataTraceFactory.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetPseudocodeTrace.java diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java index 433574fa0ac..f5077050bb4 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java @@ -34,7 +34,6 @@ import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport; import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation; import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -246,7 +245,6 @@ public class KotlinToJVMBytecodeCompiler { public AnalyzeExhaust invoke() { return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( environment.getProject(), environment.getSourceFiles(), filesToAnalyzeCompletely, - JetControlFlowDataTraceFactory.EMPTY, configuration.getEnvironment().getCompilerDependencies()); } }, environment.getSourceFiles() diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java index 18d4ddfd1c1..b1822200b66 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.psi.*; import java.util.List; @@ -64,7 +65,7 @@ public interface JetControlFlowBuilder { // Subroutines void enterSubroutine(@NotNull JetDeclaration subroutine); - void exitSubroutine(@NotNull JetDeclaration subroutine); + Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine); @NotNull JetElement getCurrentSubroutine(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java index e3f6d4df970..cb3d67b2b64 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.psi.*; import java.util.List; @@ -157,9 +158,9 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder { } @Override - public void exitSubroutine(@NotNull JetDeclaration subroutine) { + public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) { assert builder != null; - builder.exitSubroutine(subroutine); + return builder.exitSubroutine(subroutine); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 004e2cc739a..20837493531 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -21,6 +21,9 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator; +import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; @@ -45,12 +48,22 @@ public class JetControlFlowProcessor { private final JetControlFlowBuilder builder; private final BindingTrace trace; - public JetControlFlowProcessor(BindingTrace trace, JetControlFlowBuilder builder) { - this.builder = builder; + public JetControlFlowProcessor(BindingTrace trace) { + this.builder = new JetControlFlowInstructionsGenerator(); this.trace = trace; } - public void generate(@NotNull JetDeclaration subroutine) { + //todo + public Pseudocode generatePseudocode(@NotNull JetDeclaration subroutine) { + Pseudocode pseudocode = generate(subroutine); + ((PseudocodeImpl)pseudocode).postProcess(); + for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + ((PseudocodeImpl)localPseudocode).postProcess(); + } + return pseudocode; + } + + public Pseudocode generate(@NotNull JetDeclaration subroutine) { builder.enterSubroutine(subroutine); if (subroutine instanceof JetDeclarationWithBody) { JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine; @@ -67,7 +80,7 @@ public class JetControlFlowProcessor { else { subroutine.accept(new CFPVisitor(false)); } - builder.exitSubroutine(subroutine); + return builder.exitSubroutine(subroutine); } private void processLocalDeclaration(@NotNull JetDeclaration subroutine) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index a60398498ff..01558871026 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.cfg; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; @@ -33,12 +32,14 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DescriptorUtils; -import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetMainDetector; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Set; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE; @@ -49,67 +50,22 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; */ public class JetFlowInformationProvider { - private final Map pseudocodeMap; - private final Map pseudocodeDataMap; + private final JetDeclaration subroutine; + private final Pseudocode pseudocode; + private final PseudocodeData pseudocodeData; private BindingTrace trace; - public JetFlowInformationProvider(@NotNull JetDeclaration declaration, @NotNull final JetExpression bodyExpression, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace trace) { + public JetFlowInformationProvider( + @NotNull JetDeclaration declaration, + @NotNull BindingTrace trace) { + + subroutine = declaration; this.trace = trace; - final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration); - pseudocodeMap = new LinkedHashMap(); - pseudocodeDataMap = new HashMap(); - final Map representativeInstructions = new HashMap(); - final Map loopInfo = Maps.newHashMap(); - JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() { - @Override - public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) { - pseudocodeTrace.recordControlFlowData(element, pseudocode); - pseudocodeMap.put(element, pseudocode); - } - - @Override - public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) { - Instruction oldValue = representativeInstructions.put(element, instruction); -// assert oldValue == null : element.getText(); - pseudocodeTrace.recordRepresentativeInstruction(element, instruction); - } - - @Override - public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { - loopInfo.put(expression, blockInfo); - pseudocodeTrace.recordLoopInfo(expression, blockInfo); - } - - @Override - public void close() { - pseudocodeTrace.close(); - List values = Lists.newArrayList(pseudocodeMap.values()); - Collections.reverse(values); - for (Pseudocode pseudocode : values) { - pseudocode.postProcess(); - } - } - }; - JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace); - new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration); - wrappedTrace.close(); + pseudocode = new JetControlFlowProcessor(trace).generatePseudocode(declaration); + pseudocodeData = new PseudocodeData(pseudocode, trace); } - private PseudocodeData getPseudocodeData(@NotNull JetElement element) { - PseudocodeData pseudocodeData = pseudocodeDataMap.get(element); - if (pseudocodeData == null) { - Pseudocode pseudocode = pseudocodeMap.get(element); - assert pseudocode != null; - pseudocodeData = new PseudocodeData(pseudocode, trace); - pseudocodeDataMap.put(element, pseudocodeData); - } - return pseudocodeData; - } - - private void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection returnedExpressions) { - Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - + private void collectReturnExpressions(@NotNull final Collection returnedExpressions) { final Set instructions = Sets.newHashSet(pseudocode.getInstructions()); SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction(); for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) { @@ -164,14 +120,16 @@ public class JetFlowInformationProvider { } } - public void checkDefiniteReturn(@NotNull final JetDeclarationWithBody function, final @NotNull JetType expectedReturnType) { + public void checkDefiniteReturn(final @NotNull JetType expectedReturnType) { + assert subroutine instanceof JetDeclarationWithBody; + JetDeclarationWithBody function = (JetDeclarationWithBody) subroutine; assert function instanceof JetDeclaration; JetExpression bodyExpression = function.getBodyExpression(); if (bodyExpression == null) return; List returnedExpressions = Lists.newArrayList(); - collectReturnExpressions(function.asElement(), returnedExpressions); + collectReturnExpressions(returnedExpressions); boolean nothingReturned = returnedExpressions.isEmpty(); @@ -211,9 +169,6 @@ public class JetFlowInformationProvider { } private Set collectUnreachableCode(@NotNull JetElement subroutine) { - Pseudocode pseudocode = pseudocodeMap.get(subroutine); - assert pseudocode != null; - Collection unreachableElements = Lists.newArrayList(); for (Instruction deadInstruction : pseudocode.getDeadInstructions()) { if (deadInstruction instanceof JetElementInstruction && @@ -228,12 +183,11 @@ public class JetFlowInformationProvider { //////////////////////////////////////////////////////////////////////////////// // Uninitialized variables analysis - public void markUninitializedVariables(@NotNull JetElement subroutine, final boolean processLocalDeclaration) { + public void markUninitializedVariables(final boolean processLocalDeclaration) { final Collection varWithUninitializedErrorGenerated = Sets.newHashSet(); final Collection varWithValReassignErrorGenerated = Sets.newHashSet(); final boolean processClassOrObject = subroutine instanceof JetClassOrObject; - final PseudocodeData pseudocodeData = getPseudocodeData(subroutine); pseudocodeData.traverseInstructionsGraph(true, true, new PseudocodeData.TraverseInstructionGraphStrategy() { @Override public void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData) { @@ -447,20 +401,10 @@ public class JetFlowInformationProvider { } } - private void analyzeLocalDeclarations(Pseudocode pseudocode, boolean processLocalDeclaration) { - for (Instruction instruction : pseudocode.getInstructions()) { - if (instruction instanceof LocalDeclarationInstruction) { - JetElement element = ((LocalDeclarationInstruction) instruction).getElement(); - markUninitializedVariables(element, processLocalDeclaration); - } - } - } - //////////////////////////////////////////////////////////////////////////////// // "Unused variable" & "unused value" analyses - public void markUnusedVariables(@NotNull JetElement subroutine) { - final PseudocodeData pseudocodeData = getPseudocodeData(subroutine); + public void markUnusedVariables() { pseudocodeData.traverseInstructionsGraph(true, false, new PseudocodeData.TraverseInstructionGraphStrategy() { @Override public void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData) { @@ -541,8 +485,7 @@ public class JetFlowInformationProvider { //////////////////////////////////////////////////////////////////////////////// // "Unused literals" in block - public void markUnusedLiteralsInBlock(@NotNull JetElement subroutine) { - Pseudocode pseudocode = pseudocodeMap.get(subroutine); + public void markUnusedLiteralsInBlock() { assert pseudocode != null; JetControlFlowGraphTraverser traverser = JetControlFlowGraphTraverser.create(pseudocode, true, true); traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowDataTraceFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowDataTraceFactory.java deleted file mode 100644 index 3ed5e991022..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowDataTraceFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.pseudocode; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.JetElement; - -/** - * @author abreslav - */ -public interface JetControlFlowDataTraceFactory { - JetControlFlowDataTraceFactory EMPTY = new JetControlFlowDataTraceFactory() { - @NotNull - @Override - public JetPseudocodeTrace createTrace(JetElement element) { - return JetPseudocodeTrace.EMPTY; - } - }; - - @NotNull - JetPseudocodeTrace createTrace(JetElement element); -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java index db3dcea5ced..f888d1711ef 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java @@ -35,12 +35,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd private final Stack allBlocks = new Stack(); - private final JetPseudocodeTrace trace; - - public JetControlFlowInstructionsGenerator(JetPseudocodeTrace trace) { - this.trace = trace; - } - private void pushBuilder(JetElement scopingElement, JetElement subroutine) { JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(scopingElement, subroutine); builders.push(worker); @@ -49,7 +43,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd private JetControlFlowInstructionsGeneratorWorker popBuilder(@NotNull JetElement element) { JetControlFlowInstructionsGeneratorWorker worker = builders.pop(); - trace.recordControlFlowData(element, worker.getPseudocode()); if (!builders.isEmpty()) { builder = builders.peek(); } @@ -72,7 +65,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd } @Override - public void exitSubroutine(@NotNull JetDeclaration subroutine) { + public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) { super.exitSubroutine(subroutine); JetControlFlowInstructionsGeneratorWorker worker = popBuilder(subroutine); if (!builders.empty()) { @@ -80,32 +73,29 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd LocalDeclarationInstruction instruction = new LocalDeclarationInstruction(subroutine, worker.getPseudocode()); builder.add(instruction); } + return worker.getPseudocode(); } private class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder { - private final Pseudocode pseudocode; + private final PseudocodeImpl pseudocode; private final Label error; private final Label sink; private final JetElement returnSubroutine; private JetControlFlowInstructionsGeneratorWorker(@NotNull JetElement scopingElement, @NotNull JetElement returnSubroutine) { - this.pseudocode = new Pseudocode(scopingElement); + this.pseudocode = new PseudocodeImpl(scopingElement); this.error = pseudocode.createLabel("error"); this.sink = pseudocode.createLabel("sink"); this.returnSubroutine = returnSubroutine; } - public Pseudocode getPseudocode() { + public PseudocodeImpl getPseudocode() { return pseudocode; } private void add(@NotNull Instruction instruction) { pseudocode.addInstruction(instruction); - if (instruction instanceof JetElementInstruction) { - JetElementInstruction elementInstruction = (JetElementInstruction) instruction; - trace.recordRepresentativeInstruction(elementInstruction.getElement(), instruction); - } } @NotNull @@ -127,7 +117,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd loopInfo.push(blockInfo); elementToBlockInfo.put(expression, blockInfo); allBlocks.push(blockInfo); - trace.recordLoopInfo(expression, blockInfo); + pseudocode.recordLoopInfo(expression, blockInfo); return blockInfo; } @@ -202,7 +192,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd } @Override - public void exitSubroutine(@NotNull JetDeclaration subroutine) { + public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) { bindLabel(getExitPoint(subroutine)); pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "")); bindLabel(error); @@ -211,6 +201,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "")); elementToBlockInfo.remove(subroutine); allBlocks.pop(); + return null; } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetPseudocodeTrace.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetPseudocodeTrace.java deleted file mode 100644 index b3149aa1090..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetPseudocodeTrace.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.pseudocode; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.cfg.LoopInfo; -import org.jetbrains.jet.lang.psi.JetElement; -import org.jetbrains.jet.lang.psi.JetExpression; - -/** - * @author abreslav - */ -public interface JetPseudocodeTrace { - - JetPseudocodeTrace EMPTY = new JetPseudocodeTrace() { - @Override - public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) { - } - - @Override - public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) { - - } - - @Override - public void close() { - } - - @Override - public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { - - } - }; - - void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode); - void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction); - void close(); - - void recordLoopInfo(JetExpression expression, LoopInfo blockInfo); -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index bac83677def..c648dcadb03 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -32,7 +32,7 @@ import java.util.*; * @author abreslav * @author svtk */ -public class PseudocodeImpl implements IPseudocode { +public class PseudocodeImpl implements Pseudocode { public class PseudocodeLabel implements Label { private final String name; @@ -103,8 +103,8 @@ public class PseudocodeImpl implements IPseudocode { @NotNull @Override - public Set getLocalDeclarations() { - Set localDeclarations = Sets.newLinkedHashSet(); + public Set getLocalDeclarations() { + Set localDeclarations = Sets.newLinkedHashSet(); //todo look recursively inside local declarations for (Instruction instruction : instructions) { if (instruction instanceof LocalDeclarationInstruction) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index f2c17c3576b..51358d84152 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -16,22 +16,15 @@ package org.jetbrains.jet.lang.resolve; -import com.google.common.base.Predicate; -import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiErrorElement; -import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.ModuleConfiguration; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; -import org.jetbrains.jet.lang.psi.JetFile; import java.util.ArrayList; -import java.util.Collection; import java.util.List; /** diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java index 67efa73f586..8c0d02e74fa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java @@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; @@ -37,7 +36,6 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; public class ControlFlowAnalyzer { private TopDownAnalysisParameters topDownAnalysisParameters; private BindingTrace trace; - private JetControlFlowDataTraceFactory flowDataTraceFactory; @Inject public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) { @@ -49,11 +47,6 @@ public class ControlFlowAnalyzer { this.trace = trace; } - @Inject - public void setFlowDataTraceFactory(JetControlFlowDataTraceFactory flowDataTraceFactory) { - this.flowDataTraceFactory = flowDataTraceFactory; - } - public void process(@NotNull BodiesResolveContext bodiesResolveContext) { for (JetClass aClass : bodiesResolveContext.getClasses().keySet()) { if (!bodiesResolveContext.completeAnalysisNeeded(aClass)) continue; @@ -86,8 +79,8 @@ public class ControlFlowAnalyzer { private void checkClassOrObject(JetClassOrObject klass) { // A pseudocode of class initialization corresponds to a class - JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, (JetExpression) klass, flowDataTraceFactory, trace); - flowInformationProvider.markUninitializedVariables((JetElement) klass, topDownAnalysisParameters.isDeclaredLocally()); + JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, trace); + flowInformationProvider.markUninitializedVariables(topDownAnalysisParameters.isDeclaredLocally()); } private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { @@ -105,16 +98,16 @@ public class ControlFlowAnalyzer { JetExpression bodyExpression = function.getBodyExpression(); if (bodyExpression == null) return; - JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) function, bodyExpression, flowDataTraceFactory, trace); + JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) function, trace); - flowInformationProvider.checkDefiniteReturn(function, expectedReturnType); + flowInformationProvider.checkDefiniteReturn(expectedReturnType); // Property accessor is checked through initialization of a class check (at 'checkClassOrObject') boolean isPropertyAccessor = function instanceof JetPropertyAccessor; - flowInformationProvider.markUninitializedVariables(function.asElement(), topDownAnalysisParameters.isDeclaredLocally() || isPropertyAccessor); + flowInformationProvider.markUninitializedVariables(topDownAnalysisParameters.isDeclaredLocally() || isPropertyAccessor); - flowInformationProvider.markUnusedVariables(function.asElement()); + flowInformationProvider.markUnusedVariables(); - flowInformationProvider.markUnusedLiteralsInBlock(function.asElement()); + flowInformationProvider.markUnusedLiteralsInBlock(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 4fbb5f140ac..df69780606e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -23,7 +23,6 @@ import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic; import org.jetbrains.jet.lang.ModuleConfiguration; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; @@ -188,7 +187,7 @@ public class TopDownAnalyzer { TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(Predicates.alwaysFalse(), true, false); InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic( project, topDownAnalysisParameters, new ObservableBindingTrace(trace), - JetStandardClasses.FAKE_STANDARD_CLASSES_MODULE, null, ModuleConfiguration.EMPTY); + JetStandardClasses.FAKE_STANDARD_CLASSES_MODULE, ModuleConfiguration.EMPTY); injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files); } @@ -220,7 +219,7 @@ public class TopDownAnalyzer { InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic( project, topDownAnalysisParameters, new ObservableBindingTrace(trace), moduleDescriptor, - JetControlFlowDataTraceFactory.EMPTY, ModuleConfiguration.EMPTY); + ModuleConfiguration.EMPTY); injector.getTopDownAnalyzer().doProcess(outerScope, new NamespaceLikeBuilder() { diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index 977b914fb4d..165ef5e7c04 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -33,7 +33,6 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Severity; @@ -170,8 +169,8 @@ public class JetTestUtils { private JetTestUtils() { } - public static AnalyzeExhaust analyzeFile(@NotNull JetFile namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { - return AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(namespace, flowDataTraceFactory, + public static AnalyzeExhaust analyzeFile(@NotNull JetFile namespace) { + return AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(namespace, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true)); } diff --git a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java index 1b1c6a00665..17aa231055b 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java @@ -28,10 +28,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; -import org.jetbrains.jet.lang.cfg.LoopInfo; +import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; import org.jetbrains.jet.lang.cfg.pseudocode.*; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; +import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; +import org.jetbrains.jet.util.slicedmap.WritableSlice; import java.io.File; import java.io.FileNotFoundException; @@ -72,37 +78,46 @@ public class JetControlFlowTest extends JetLiteFixture { JetFile file = loadPsiFile(myName + ".jet"); final Map data = new LinkedHashMap(); - final JetPseudocodeTrace pseudocodeTrace = new JetPseudocodeTrace() { + AnalyzeExhaust analyzeExhaust = JetTestUtils.analyzeFile(file); + List declarations = file.getDeclarations(); + final BindingContext bindingContext = analyzeExhaust.getBindingContext(); + BindingTrace mockTrace = new BindingTrace() { @Override - public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) { - data.put(element, pseudocode); + public BindingContext getBindingContext() { + return bindingContext; } @Override - public void close() { - for (Pseudocode pseudocode : data.values()) { - pseudocode.postProcess(); - } + public void record(WritableSlice slice, K key, V value) { } @Override - public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { + public void record(WritableSlice slice, K key) { } @Override - public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) { + public V get(ReadOnlySlice slice, K key) { + return bindingContext.get(slice, key); } - }; - - JetTestUtils.analyzeFile(file, new JetControlFlowDataTraceFactory() { @NotNull @Override - public JetPseudocodeTrace createTrace(JetElement element) { - return pseudocodeTrace; + public Collection getKeys(WritableSlice slice) { + return bindingContext.getKeys(slice); } - }); + + @Override + public void report(@NotNull Diagnostic diagnostic) { + } + }; + for (JetDeclaration declaration : declarations) { + Pseudocode pseudocode = new JetControlFlowProcessor(mockTrace).generatePseudocode(declaration); + data.put(declaration, pseudocode); + for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + data.put(localPseudocode.getCorrespondingElement(), localPseudocode); + } + } try { processCFData(myName, data); @@ -123,6 +138,7 @@ public class JetControlFlowTest extends JetLiteFixture { StringBuilder instructionDump = new StringBuilder(); int i = 0; for (Pseudocode pseudocode : pseudocodes) { + JetElement correspondingElement = pseudocode.getCorrespondingElement(); String label = ""; assert (correspondingElement instanceof JetNamedDeclaration || correspondingElement instanceof JetSecondaryConstructor || correspondingElement instanceof JetPropertyAccessor) : @@ -146,11 +162,11 @@ public class JetControlFlowTest extends JetLiteFixture { instructionDump.append(correspondingElement.getText()); instructionDump.append("\n---------------------\n"); - dumpInstructions(pseudocode, instructionDump); + dumpInstructions((PseudocodeImpl) pseudocode, instructionDump); instructionDump.append("=====================\n"); //check edges directions - Collection instructions = pseudocode.getMutableInstructionList(); + Collection instructions = ((PseudocodeImpl)pseudocode).getMutableInstructionList(); for (Instruction instruction : instructions) { if (!((InstructionImpl)instruction).isDead()) { for (Instruction nextInstruction : instruction.getNextInstructions()) { @@ -181,7 +197,7 @@ public class JetControlFlowTest extends JetLiteFixture { // } } - public void dfsDump(Pseudocode pseudocode, StringBuilder nodes, StringBuilder edges, Map nodeNames) { + public void dfsDump(PseudocodeImpl pseudocode, StringBuilder nodes, StringBuilder edges, Map nodeNames) { dfsDump(nodes, edges, pseudocode.getMutableInstructionList().get(0), nodeNames); } @@ -243,11 +259,11 @@ public class JetControlFlowTest extends JetLiteFixture { return sb.toString(); } - public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) { + public void dumpInstructions(PseudocodeImpl pseudocode, @NotNull StringBuilder out) { List instructions = pseudocode.getMutableInstructionList(); Set remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions()); - List labels = pseudocode.getLabels(); - List locals = new ArrayList(); + List labels = pseudocode.getLabels(); + List locals = new ArrayList(); int maxLength = 0; int maxNextLength = 0; for (Instruction instruction : instructions) { @@ -276,9 +292,9 @@ public class JetControlFlowTest extends JetLiteFixture { Instruction instruction = instructions.get(i); if (instruction instanceof LocalDeclarationInstruction) { LocalDeclarationInstruction localDeclarationInstruction = (LocalDeclarationInstruction) instruction; - locals.add(localDeclarationInstruction.getBody()); + locals.add((PseudocodeImpl) localDeclarationInstruction.getBody()); } - for (Pseudocode.PseudocodeLabel label: labels) { + for (PseudocodeImpl.PseudocodeLabel label: labels) { if (label.getTargetInstructionIndex() == i) { out.append(label.getName()).append(":\n"); } @@ -288,7 +304,7 @@ public class JetControlFlowTest extends JetLiteFixture { append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))). append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n"); } - for (Pseudocode local : locals) { + for (PseudocodeImpl local : locals) { dumpInstructions(local, out); } } @@ -300,7 +316,7 @@ public class JetControlFlowTest extends JetLiteFixture { public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) { int index = count[0]; // instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName); - printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getMutableInstructionList().get(0)), null); + printEdge(out, nodeToName.get(instruction), nodeToName.get(((PseudocodeImpl)instruction.getBody()).getMutableInstructionList().get(0)), null); visitInstructionWithNext(instruction); } @@ -415,7 +431,7 @@ public class JetControlFlowTest extends JetLiteFixture { int[] count = new int[1]; Map nodeToName = new HashMap(); for (Pseudocode pseudocode : pseudocodes) { - dumpNodes(pseudocode.getMutableInstructionList(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions())); + dumpNodes(((PseudocodeImpl)pseudocode).getMutableInstructionList(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions())); } int i = 0; for (Pseudocode pseudocode : pseudocodes) { @@ -431,7 +447,7 @@ public class JetControlFlowTest extends JetLiteFixture { out.println("subgraph cluster_" + i + " {\n" + "label=\"" + label + "\";\n" + "color=blue;\n"); - dumpEdges(pseudocode.getMutableInstructionList(), out, count, nodeToName); + dumpEdges(((PseudocodeImpl)pseudocode).getMutableInstructionList(), out, count, nodeToName); out.println("}"); i++; } diff --git a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java index 1a19a747b47..04c98039da6 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java @@ -21,7 +21,6 @@ import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.CompileCompilerDependenciesTest; import org.jetbrains.jet.JetLiteFixture; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -107,8 +106,7 @@ public class CheckerTestUtilTest extends JetLiteFixture { public void test(final @NotNull PsiFile psiFile) { BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration( - (JetFile) psiFile, JetControlFlowDataTraceFactory.EMPTY, - CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true)) + (JetFile) psiFile, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true)) .getBindingContext(); String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile)).toString(); diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java index 1cf8e9bbc76..41ffe49a171 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java @@ -29,7 +29,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; @@ -172,9 +171,7 @@ public class JetDiagnosticsTest extends JetLiteFixture { } BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - getProject(), jetFiles, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY, - myEnvironment.getCompilerDependencies()) - .getBindingContext(); + getProject(), jetFiles, Predicates.alwaysTrue(), myEnvironment.getCompilerDependencies()).getBindingContext(); boolean ok = true; diff --git a/compiler/tests/org/jetbrains/jet/cli/jvm/compiler/ReadJavaBinaryClassTest.java b/compiler/tests/org/jetbrains/jet/cli/jvm/compiler/ReadJavaBinaryClassTest.java index 47f541038ca..c380734a4da 100644 --- a/compiler/tests/org/jetbrains/jet/cli/jvm/compiler/ReadJavaBinaryClassTest.java +++ b/compiler/tests/org/jetbrains/jet/cli/jvm/compiler/ReadJavaBinaryClassTest.java @@ -26,7 +26,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.di.InjectorForJavaSemanticServices; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -87,8 +86,7 @@ public class ReadJavaBinaryClassTest extends TestCaseWithTmpdir { JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( - psiFile, JetControlFlowDataTraceFactory.EMPTY, - jetCoreEnvironment.getCompilerDependencies()) + psiFile, jetCoreEnvironment.getCompilerDependencies()) .getBindingContext(); return bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, FqName.topLevel(Name.identifier("test"))); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 1258db8df17..a782ce77563 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; @@ -186,8 +185,7 @@ public abstract class CodegenTestCase extends UsefulTestCase { private GenerationState generateCommon(ClassBuilderFactory classBuilderFactory) { final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( - myFile, JetControlFlowDataTraceFactory.EMPTY, - myEnvironment.getCompilerDependencies()); + myFile, myEnvironment.getCompilerDependencies()); analyzeExhaust.throwIfError(); AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext()); GenerationState state = new GenerationState(myEnvironment.getProject(), classBuilderFactory, analyzeExhaust, Collections.singletonList(myFile)); diff --git a/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java b/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java index 6875096cb1c..bfa1b4f5d1c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java +++ b/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java @@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.CompileCompilerDependenciesTest; import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; @@ -37,8 +36,7 @@ public class GenerationUtils { public static GenerationState compileFileGetGenerationStateForTest(JetFile psiFile, @NotNull CompilerSpecialMode compilerSpecialMode) { final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( - psiFile, JetControlFlowDataTraceFactory.EMPTY, - CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode, true)); + psiFile, CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode, true)); analyzeExhaust.throwIfError(); GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.binaries(false), analyzeExhaust, Collections.singletonList(psiFile)); state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION); diff --git a/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java b/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java index 839500889d3..f9d1682cbd8 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java +++ b/compiler/tests/org/jetbrains/jet/resolve/DescriptorRendererTest.java @@ -22,7 +22,6 @@ import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetFile; @@ -78,8 +77,7 @@ public class DescriptorRendererTest extends JetLiteFixture { JetFile psiFile = createPsiFile(null, fileName, loadFile(fileName)); AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration( - (JetFile) psiFile, JetControlFlowDataTraceFactory.EMPTY, - myEnvironment.getCompilerDependencies()); + (JetFile) psiFile, myEnvironment.getCompilerDependencies()); final BindingContext bindingContext = analyzeExhaust.getBindingContext(); final List descriptors = new ArrayList(); psiFile.acceptChildren(new JetVisitorVoid() { diff --git a/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java b/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java index f17692228d6..3e04ae4fa64 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java +++ b/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java @@ -27,7 +27,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; @@ -154,8 +153,7 @@ public abstract class ExpectedResolveData { JetStandardLibrary lib = JetStandardLibrary.getInstance(); AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(project, files, - Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY, - jetCoreEnvironment.getCompilerDependencies()); + Predicates.alwaysTrue(), jetCoreEnvironment.getCompilerDependencies()); BindingContext bindingContext = analyzeExhaust.getBindingContext(); for (Diagnostic diagnostic : bindingContext.getDiagnostics()) { if (diagnostic.getFactory() instanceof UnresolvedReferenceDiagnosticFactory) { diff --git a/compiler/tests/org/jetbrains/jet/types/JetDefaultModalityModifiersTest.java b/compiler/tests/org/jetbrains/jet/types/JetDefaultModalityModifiersTest.java index b4c70e9637a..70598372894 100644 --- a/compiler/tests/org/jetbrains/jet/types/JetDefaultModalityModifiersTest.java +++ b/compiler/tests/org/jetbrains/jet/types/JetDefaultModalityModifiersTest.java @@ -20,7 +20,6 @@ import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.di.InjectorForTests; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -66,7 +65,6 @@ public class JetDefaultModalityModifiersTest extends JetLiteFixture { JetDeclaration aClass = declarations.get(0); assert aClass instanceof JetClass; AnalyzeExhaust bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(file, - JetControlFlowDataTraceFactory.EMPTY, myEnvironment.getCompilerDependencies()); DeclarationDescriptor classDescriptor = bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass); WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING); diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java index f335cb132ee..28896d9b8c1 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java @@ -33,7 +33,6 @@ import com.intellij.psi.util.PsiTreeUtil; import jet.Tuple2; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -74,8 +73,7 @@ public class JetSourceNavigationHelper { BindingContext bindingContext = AnalyzerFacadeProvider.getAnalyzerFacadeForProject(project).analyzeFiles( project, libraryFiles, - Predicates.alwaysTrue(), - JetControlFlowDataTraceFactory.EMPTY).getBindingContext(); + Predicates.alwaysTrue()).getBindingContext(); D descriptor = bindingContext.get(slice, fqName); if (descriptor != null) { return new Tuple2(bindingContext, descriptor); diff --git a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java index 662e9f816a7..2c026928cc6 100644 --- a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java +++ b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java @@ -26,7 +26,6 @@ import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.ScriptCodegen; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.jet.lang.ModuleConfiguration; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.*; @@ -93,7 +92,6 @@ public class AllInjectorsGenerator { generator.addPublicParameter(TopDownAnalysisParameters.class); generator.addPublicParameter(ObservableBindingTrace.class); generator.addParameter(ModuleDescriptor.class); - generator.addParameter(JetControlFlowDataTraceFactory.class, false); } private static void generateMacroInjector() throws IOException { From 7a02cfcd25b1a29bcc8c3149ce022132e304f5b7 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 12:46:38 +0400 Subject: [PATCH 08/24] order of declaration changed in tests --- .../cfg/AnonymousInitializers.instructions | 26 +-- compiler/testData/cfg/Basic.instructions | 26 +-- compiler/testData/cfg/Finally.instructions | 126 +++++++------- .../cfg/LocalDeclarations.instructions | 156 ++++++------------ 4 files changed, 143 insertions(+), 191 deletions(-) diff --git a/compiler/testData/cfg/AnonymousInitializers.instructions b/compiler/testData/cfg/AnonymousInitializers.instructions index 32d8f65e3a2..d513fda9296 100644 --- a/compiler/testData/cfg/AnonymousInitializers.instructions +++ b/compiler/testData/cfg/AnonymousInitializers.instructions @@ -1,16 +1,3 @@ -== get_j == -get() = 20 ---------------------- -l0: - NEXT:[r(20)] PREV:[] - r(20) NEXT:[] PREV:[] -l1: - NEXT:[] PREV:[r(20)] -error: - NEXT:[] PREV:[] -sink: - NEXT:[] PREV:[, ] -===================== == AnonymousInitializers == class AnonymousInitializers() { val k = 34 @@ -59,3 +46,16 @@ error: sink: NEXT:[] PREV:[, ] ===================== +== get_j == +get() = 20 +--------------------- +l3: + NEXT:[r(20)] PREV:[] + r(20) NEXT:[] PREV:[] +l4: + NEXT:[] PREV:[r(20)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] +===================== diff --git a/compiler/testData/cfg/Basic.instructions b/compiler/testData/cfg/Basic.instructions index abd49b300ab..a3ddadb3a30 100644 --- a/compiler/testData/cfg/Basic.instructions +++ b/compiler/testData/cfg/Basic.instructions @@ -1,16 +1,3 @@ -== anonymous_0 == -{1} ---------------------- -l3: - NEXT:[r(1)] PREV:[] - r(1) NEXT:[] PREV:[] -l4: - NEXT:[] PREV:[r(1)] -error: - NEXT:[] PREV:[] -sink: - NEXT:[] PREV:[, ] -===================== == f == fun f(a : Boolean) : Unit { 1 @@ -91,6 +78,19 @@ error: sink: NEXT:[] PREV:[, ] ===================== +== anonymous_0 == +{1} +--------------------- +l3: + NEXT:[r(1)] PREV:[] + r(1) NEXT:[] PREV:[] +l4: + NEXT:[] PREV:[r(1)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] +===================== == foo == fun foo(a : Boolean, b : Int) : Unit {} --------------------- diff --git a/compiler/testData/cfg/Finally.instructions b/compiler/testData/cfg/Finally.instructions index d9ef32e086e..470a05454b2 100644 --- a/compiler/testData/cfg/Finally.instructions +++ b/compiler/testData/cfg/Finally.instructions @@ -69,33 +69,6 @@ error: sink: NEXT:[] PREV:[, ] ===================== -== anonymous_0 == -{ () => - if (2 > 3) { - return@ - } - } ---------------------- -l3: - NEXT:[r(())] PREV:[] - r(()) NEXT:[r(2)] PREV:[] - r(2) NEXT:[r(3)] PREV:[r(())] - r(3) NEXT:[r(>)] PREV:[r(2)] - r(>) NEXT:[r(2 > 3)] PREV:[r(3)] - r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] - jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)] - ret l4 NEXT:[] PREV:[jf(l5)] -- jmp(l6) NEXT:[] PREV:[] -l5: - read (Unit) NEXT:[] PREV:[jf(l5)] -l4: -l6: - NEXT:[] PREV:[ret l4, read (Unit)] -error: - NEXT:[] PREV:[] -sink: - NEXT:[] PREV:[, ] -===================== == t3 == fun t3() { try { @@ -164,50 +137,32 @@ error: sink: NEXT:[] PREV:[, ] ===================== -== anonymous_1 == +== anonymous_0 == { () => - try { - 1 - if (2 > 3) { - return@ - } - } finally { - 2 + if (2 > 3) { + return@ + } } - } --------------------- l3: - NEXT:[r(())] PREV:[] - r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[] - r(try { - 1 - if (2 > 3) { - return@ - } - } finally { - 2 - }) NEXT:[r(1)] PREV:[r(())] - r(1) NEXT:[r(2)] PREV:[r(try { 1 if (2 > 3) { retur..)] - r(2) NEXT:[r(3)] PREV:[r(1)] - r(3) NEXT:[r(>)] PREV:[r(2)] - r(>) NEXT:[r(2 > 3)] PREV:[r(3)] - r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] - jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)] - r(2) NEXT:[ret l4] PREV:[jf(l5)] - ret l4 NEXT:[] PREV:[r(2)] -- jmp(l6) NEXT:[r(2)] PREV:[] + NEXT:[r(())] PREV:[] + r(()) NEXT:[r(2)] PREV:[] + r(2) NEXT:[r(3)] PREV:[r(())] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] + jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)] + ret l4 NEXT:[] PREV:[jf(l5)] +- jmp(l6) NEXT:[] PREV:[] l5: - read (Unit) NEXT:[r(2)] PREV:[jf(l5)] -l6: -l7: - r(2) NEXT:[] PREV:[read (Unit)] + read (Unit) NEXT:[] PREV:[jf(l5)] l4: -l8: - NEXT:[] PREV:[ret l4, r(2)] +l6: + NEXT:[] PREV:[ret l4, read (Unit)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[, ] + NEXT:[] PREV:[, ] ===================== == t4 == fun t4() { @@ -286,6 +241,51 @@ error: sink: NEXT:[] PREV:[, ] ===================== +== anonymous_1 == +{ () => + try { + 1 + if (2 > 3) { + return@ + } + } finally { + 2 + } + } +--------------------- +l3: + NEXT:[r(())] PREV:[] + r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[] + r(try { + 1 + if (2 > 3) { + return@ + } + } finally { + 2 + }) NEXT:[r(1)] PREV:[r(())] + r(1) NEXT:[r(2)] PREV:[r(try { 1 if (2 > 3) { retur..)] + r(2) NEXT:[r(3)] PREV:[r(1)] + r(3) NEXT:[r(>)] PREV:[r(2)] + r(>) NEXT:[r(2 > 3)] PREV:[r(3)] + r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)] + jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)] + r(2) NEXT:[ret l4] PREV:[jf(l5)] + ret l4 NEXT:[] PREV:[r(2)] +- jmp(l6) NEXT:[r(2)] PREV:[] +l5: + read (Unit) NEXT:[r(2)] PREV:[jf(l5)] +l6: +l7: + r(2) NEXT:[] PREV:[read (Unit)] +l4: +l8: + NEXT:[] PREV:[ret l4, r(2)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] +===================== == t5 == fun t5() { @ while(true) { diff --git a/compiler/testData/cfg/LocalDeclarations.instructions b/compiler/testData/cfg/LocalDeclarations.instructions index 500f605b982..388bf6cb715 100644 --- a/compiler/testData/cfg/LocalDeclarations.instructions +++ b/compiler/testData/cfg/LocalDeclarations.instructions @@ -29,53 +29,6 @@ error: sink: NEXT:[] PREV:[, ] ===================== -== O == -object O { - val x : Int - { - $x = 1 - } -} ---------------------- -l0: - NEXT:[v(val x : Int)] PREV:[] - v(val x : Int) NEXT:[r(1)] PREV:[] - r(1) NEXT:[w($x)] PREV:[v(val x : Int)] - w($x) NEXT:[] PREV:[r(1)] -l1: - NEXT:[] PREV:[w($x)] -error: - NEXT:[] PREV:[] -sink: - NEXT:[] PREV:[, ] -===================== -== null == -object { - val x : Int - - { - $x = 1 - } - - - fun foo() { - val b : Int = 1 - doSmth(b) - } - } ---------------------- -l0: - NEXT:[v(val x : Int)] PREV:[] - v(val x : Int) NEXT:[r(1)] PREV:[] - r(1) NEXT:[w($x)] PREV:[v(val x : Int)] - w($x) NEXT:[] PREV:[r(1)] -l1: - NEXT:[] PREV:[w($x)] -error: - NEXT:[] PREV:[] -sink: - NEXT:[] PREV:[, ] -===================== == doSmth == fun doSmth(i: Int) {} --------------------- @@ -126,6 +79,26 @@ error: sink: NEXT:[] PREV:[, ] ===================== +== O == +object O { + val x : Int + { + $x = 1 + } +} +--------------------- +l0: + NEXT:[v(val x : Int)] PREV:[] + v(val x : Int) NEXT:[r(1)] PREV:[] + r(1) NEXT:[w($x)] PREV:[v(val x : Int)] + w($x) NEXT:[] PREV:[r(1)] +l1: + NEXT:[] PREV:[w($x)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] +===================== == test2 == fun test2() { val b = 1 @@ -156,22 +129,6 @@ error: sink: NEXT:[] PREV:[, ] ===================== -== inner_bar == -fun inner_bar() { - y = 10 - } ---------------------- -l3: - NEXT:[r(10)] PREV:[] - r(10) NEXT:[w(y)] PREV:[] - w(y) NEXT:[] PREV:[r(10)] -l4: - NEXT:[] PREV:[w(y)] -error: - NEXT:[] PREV:[] -sink: - NEXT:[] PREV:[, ] -===================== == test3 == fun test3() { val a = object { @@ -220,8 +177,8 @@ error: sink: NEXT:[] PREV:[, ] ===================== -== ggg == -fun ggg() { +== inner_bar == +fun inner_bar() { y = 10 } --------------------- @@ -299,33 +256,17 @@ error: sink: NEXT:[] PREV:[, ] ===================== -== foo == -fun foo() { - x = 3 +== ggg == +fun ggg() { + y = 10 } --------------------- l3: - NEXT:[r(3)] PREV:[] - r(3) NEXT:[w(x)] PREV:[] - w(x) NEXT:[] PREV:[r(3)] + NEXT:[r(10)] PREV:[] + r(10) NEXT:[w(y)] PREV:[] + w(y) NEXT:[] PREV:[r(10)] l4: - NEXT:[] PREV:[w(x)] -error: - NEXT:[] PREV:[] -sink: - NEXT:[] PREV:[, ] -===================== -== bar == -fun bar() { - x = 4 - } ---------------------- -l6: - NEXT:[r(4)] PREV:[] - r(4) NEXT:[w(x)] PREV:[] - w(x) NEXT:[] PREV:[r(4)] -l7: - NEXT:[] PREV:[w(x)] + NEXT:[] PREV:[w(y)] error: NEXT:[] PREV:[] sink: @@ -418,22 +359,33 @@ sink: ===================== == foo == fun foo() { - val b : Int = 1 - doSmth(b) + x = 3 } --------------------- -l0: - NEXT:[v(val b : Int = 1)] PREV:[] - v(val b : Int = 1) NEXT:[r(1)] PREV:[] - r(1) NEXT:[w(b)] PREV:[v(val b : Int = 1)] - w(b) NEXT:[r(b)] PREV:[r(1)] - r(b) NEXT:[r(doSmth)] PREV:[w(b)] - r(doSmth) NEXT:[r(doSmth(b))] PREV:[r(b)] - r(doSmth(b)) NEXT:[] PREV:[r(doSmth)] -l1: - NEXT:[] PREV:[r(doSmth(b))] +l3: + NEXT:[r(3)] PREV:[] + r(3) NEXT:[w(x)] PREV:[] + w(x) NEXT:[] PREV:[r(3)] +l4: + NEXT:[] PREV:[w(x)] error: - NEXT:[] PREV:[] + NEXT:[] PREV:[] sink: - NEXT:[] PREV:[, ] + NEXT:[] PREV:[, ] +===================== +== bar == +fun bar() { + x = 4 + } +--------------------- +l6: + NEXT:[r(4)] PREV:[] + r(4) NEXT:[w(x)] PREV:[] + w(x) NEXT:[] PREV:[r(4)] +l7: + NEXT:[] PREV:[w(x)] +error: + NEXT:[] PREV:[] +sink: + NEXT:[] PREV:[, ] ===================== From 5c7206ef4915f6cf80020daa1611bca2dc4024a8 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 13:34:05 +0400 Subject: [PATCH 09/24] 'Pseudocode' interface improvements --- .../cfg/JetControlFlowGraphTraverser.java | 39 +++-------- .../jet/lang/cfg/JetControlFlowProcessor.java | 5 +- .../lang/cfg/JetFlowInformationProvider.java | 8 +-- .../jet/lang/cfg/data/PseudocodeData.java | 8 ++- .../LocalDeclarationInstruction.java | 7 ++ .../jet/lang/cfg/pseudocode/Pseudocode.java | 5 +- .../lang/cfg/pseudocode/PseudocodeImpl.java | 66 +++++++++++++------ 7 files changed, 78 insertions(+), 60 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java index 7fd6e252c82..874f163e514 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -32,22 +32,22 @@ import java.util.*; public class JetControlFlowGraphTraverser { private final Pseudocode pseudocode; private final boolean lookInside; - private final boolean straightDirection; + private final boolean directOrder; private final Map> dataMap = Maps.newLinkedHashMap(); public static JetControlFlowGraphTraverser create(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) { return new JetControlFlowGraphTraverser(pseudocode, lookInside, straightDirection); } - private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) { + private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean directOrder) { this.pseudocode = pseudocode; this.lookInside = lookInside; - this.straightDirection = straightDirection; + this.directOrder = directOrder; } @NotNull private Instruction getStartInstruction(@NotNull Pseudocode pseudocode) { - return straightDirection ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); + return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } @NotNull @@ -84,42 +84,21 @@ public class JetControlFlowGraphTraverser { } } - private static List reverseInstructions(@NotNull Pseudocode pseudocode) { - LinkedHashSet traversedInstructions = Sets.newLinkedHashSet(); - Instruction sinkInstruction = pseudocode.getSinkInstruction(); - traverseInstructions(sinkInstruction, traversedInstructions); - return Lists.newArrayList(traversedInstructions); - } - - private static void traverseInstructions(@NotNull Instruction instruction, @NotNull LinkedHashSet instructions) { - if (((InstructionImpl)instruction).isDead()) return; - if (instructions.contains(instruction)) return; - instructions.add(instruction); - for (Instruction previousInstruction : instruction.getPreviousInstructions()) { - traverseInstructions(previousInstruction, instructions); - } - } - private void traverseSubGraph( @NotNull Pseudocode pseudocode, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, @NotNull Collection previousSubGraphInstructions, boolean[] changed, boolean isLocal) { - List instructions = pseudocode.getInstructions(); + List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); Instruction startInstruction = getStartInstruction(pseudocode); - if (!straightDirection) { - instructions = reverseInstructions(pseudocode); - } for (Instruction instruction : instructions) { - boolean isStart = straightDirection ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; + boolean isStart = directOrder ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; if (!isLocal && isStart) continue; Collection allPreviousInstructions; - Collection previousInstructions = straightDirection - ? instruction.getPreviousInstructions() - : instruction.getNextInstructions(); + Collection previousInstructions = directOrder ? instruction.getPreviousInstructions() : instruction.getNextInstructions(); if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) { allPreviousInstructions = Lists.newArrayList(previousInstructions); @@ -132,7 +111,7 @@ public class JetControlFlowGraphTraverser { if (lookInside && instruction instanceof LocalDeclarationInstruction) { Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); traverseSubGraph(subroutinePseudocode, instructionDataMergeStrategy, previousInstructions, changed, true); - Instruction lastInstruction = straightDirection ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); + Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); Pair previousValue = dataMap.get(instruction); Pair newValue = dataMap.get(lastInstruction); if (!previousValue.equals(newValue)) { @@ -168,7 +147,7 @@ public class JetControlFlowGraphTraverser { @NotNull Pseudocode pseudocode, @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { List instructions = pseudocode.getInstructions(); - if (!straightDirection) { + if (!directOrder) { instructions = Lists.newArrayList(instructions); Collections.reverse(instructions); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 20837493531..fa4d265e80f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction; import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator; import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl; @@ -57,8 +58,8 @@ public class JetControlFlowProcessor { public Pseudocode generatePseudocode(@NotNull JetDeclaration subroutine) { Pseudocode pseudocode = generate(subroutine); ((PseudocodeImpl)pseudocode).postProcess(); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { - ((PseudocodeImpl)localPseudocode).postProcess(); + for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { + ((PseudocodeImpl)localDeclarationInstruction.getBody()).postProcess(); } return pseudocode; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 01558871026..c643fe1a65b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -140,7 +140,7 @@ public class JetFlowInformationProvider { } final boolean blockBody = function.hasBlockBody(); - final Set rootUnreachableElements = collectUnreachableCode(function.asElement()); + final Set rootUnreachableElements = collectUnreachableCode(); for (JetElement element : rootUnreachableElements) { trace.report(UNREACHABLE_CODE.on(element)); } @@ -168,7 +168,7 @@ public class JetFlowInformationProvider { } } - private Set collectUnreachableCode(@NotNull JetElement subroutine) { + private Set collectUnreachableCode() { Collection unreachableElements = Lists.newArrayList(); for (Instruction deadInstruction : pseudocode.getDeadInstructions()) { if (deadInstruction instanceof JetElementInstruction && @@ -223,8 +223,8 @@ public class JetFlowInformationProvider { Pseudocode pseudocode = pseudocodeData.getPseudocode(); recordInitializedVariables(pseudocodeData.getDeclarationData(pseudocode), pseudocodeData.getResultInfo(pseudocode)); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { - recordInitializedVariables(pseudocodeData.getDeclarationData(localPseudocode), pseudocodeData.getResultInfo(localPseudocode)); + for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) { + recordInitializedVariables(pseudocodeData.getDeclarationData(instruction.getBody()), pseudocodeData.getResultInfo(instruction.getBody())); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java index d78011e47a4..ccb6173d932 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java @@ -119,8 +119,8 @@ public class PseudocodeData { DeclarationData declarationData = new DeclarationData(pseudocode.getCorrespondingElement(), this, collectDeclaredVariables(pseudocode), collectUsedVariables(pseudocode)); declarationDataMap.put(pseudocode, declarationData); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { - collectDeclarationData(localPseudocode); + for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { + collectDeclarationData(localDeclarationInstruction.getBody()); } } @@ -180,7 +180,9 @@ public class PseudocodeData { Map, Map>> result = traverser.getDataMap(); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + + for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { + Pseudocode localPseudocode = localDeclarationInstruction.getBody(); Map, Map>> initializersForLocalDeclaration = collectVariableInitializers(localPseudocode, declarationDataMap.get(localPseudocode)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java index 990c2142c9c..fd8639d94f9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetElement; import java.util.ArrayList; import java.util.Collection; @@ -40,6 +41,12 @@ public class LocalDeclarationInstruction extends InstructionWithNext { return body; } + @NotNull + @Override + public JetDeclaration getElement() { + return (JetDeclaration) super.getElement(); + } + @NotNull @Override public Collection getNextInstructions() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index 85d141b7e21..8394b6725ce 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -30,11 +30,14 @@ public interface Pseudocode { JetElement getCorrespondingElement(); @NotNull - Set getLocalDeclarations(); + Set getLocalDeclarations(); @NotNull List getInstructions(); + @NotNull + List getReversedInstructions(); + @NotNull List getDeadInstructions(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index c648dcadb03..8eb651cf4a0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -76,10 +76,13 @@ public class PseudocodeImpl implements Pseudocode { private final List mutableInstructionList = new ArrayList(); private final List instructions = new ArrayList(); + private List reversedInstructions = null; private List deadInstructions; - final Map representativeInstructions = new HashMap(); - final Map loopInfo = Maps.newHashMap(); + private Set localDeclarations = null; + //todo getters + private final Map representativeInstructions = new HashMap(); + private final Map loopInfo = Maps.newHashMap(); private final List labels = new ArrayList(); private final List allowedDeadLabels = new ArrayList(); @@ -103,28 +106,30 @@ public class PseudocodeImpl implements Pseudocode { @NotNull @Override - public Set getLocalDeclarations() { - Set localDeclarations = Sets.newLinkedHashSet(); - //todo look recursively inside local declarations - for (Instruction instruction : instructions) { - if (instruction instanceof LocalDeclarationInstruction) { - localDeclarations.add(((LocalDeclarationInstruction) instruction).getBody()); + public Set getLocalDeclarations() { + if (localDeclarations == null) { + localDeclarations = Sets.newLinkedHashSet(); + //todo look recursively inside local declarations + for (Instruction instruction : instructions) { + if (instruction instanceof LocalDeclarationInstruction) { + localDeclarations.add((LocalDeclarationInstruction) instruction); + } } } return localDeclarations; } - public PseudocodeLabel createLabel(String name) { + /*package*/ PseudocodeLabel createLabel(String name) { PseudocodeLabel label = new PseudocodeLabel(name); labels.add(label); return label; } - public void allowDead(Label label) { + /*package*/ void allowDead(Label label) { allowedDeadLabels.add((PseudocodeLabel) label); } - public void stopAllowDead(Label label) { + /*package*/ void stopAllowDead(Label label) { stopAllowDeadLabels.add((PseudocodeLabel) label); } @@ -134,9 +139,30 @@ public class PseudocodeImpl implements Pseudocode { return instructions; } - @Deprecated //for tests only @NotNull - public List getMutableInstructionList() { + @Override + public List getReversedInstructions() { + if (reversedInstructions == null) { + LinkedHashSet traversedInstructions = Sets.newLinkedHashSet(); + traverseInstructionsInReverseOrder(sinkInstruction, traversedInstructions); + reversedInstructions = Lists.newArrayList(traversedInstructions); + } + return reversedInstructions; + } + + private static void traverseInstructionsInReverseOrder(@NotNull Instruction instruction, + @NotNull LinkedHashSet instructions) { + if (instructions.contains(instruction)) return; + instructions.add(instruction); + for (Instruction previousInstruction : instruction.getPreviousInstructions()) { + traverseInstructionsInReverseOrder(previousInstruction, instructions); + } + } + + + //for tests only + @NotNull + public List getAllInstructions() { return mutableInstructionList; } @@ -159,31 +185,31 @@ public class PseudocodeImpl implements Pseudocode { return deadInstructions; } - @Deprecated //for tests only + //for tests only @NotNull public List getLabels() { return labels; } - public void addExitInstruction(SubroutineExitInstruction exitInstruction) { + /*package*/ void addExitInstruction(SubroutineExitInstruction exitInstruction) { addInstruction(exitInstruction); assert this.exitInstruction == null; this.exitInstruction = exitInstruction; } - public void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) { + /*package*/ void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) { addInstruction(sinkInstruction); assert this.sinkInstruction == null; this.sinkInstruction = sinkInstruction; } - public void addErrorInstruction(SubroutineExitInstruction errorInstruction) { + /*package*/ void addErrorInstruction(SubroutineExitInstruction errorInstruction) { addInstruction(errorInstruction); assert this.errorInstruction == null; this.errorInstruction = errorInstruction; } - public void addInstruction(Instruction instruction) { + /*package*/ void addInstruction(Instruction instruction) { mutableInstructionList.add(instruction); instruction.setOwner(this); @@ -193,7 +219,7 @@ public class PseudocodeImpl implements Pseudocode { } } - public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { + /*package*/ void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { loopInfo.put(expression, blockInfo); } @@ -215,7 +241,7 @@ public class PseudocodeImpl implements Pseudocode { return (SubroutineEnterInstruction) mutableInstructionList.get(0); } - public void bindLabel(Label label) { + /*package*/ void bindLabel(Label label) { ((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size()); } From ac41cab3406c473d22a7ca9acc015edbf2e1fed4 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 13:34:29 +0400 Subject: [PATCH 10/24] added PseudocodeUtil responsible for creation --- .../lang/cfg/pseudocode/PseudocodeUtil.java | 69 +++++++++++++++++++ .../jetbrains/jet/cfg/JetControlFlowTest.java | 54 +++------------ 2 files changed, 79 insertions(+), 44 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java new file mode 100644 index 00000000000..3612cc1a997 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.pseudocode; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; +import org.jetbrains.jet.util.slicedmap.WritableSlice; + +import java.util.Collection; + +/** + * @author svtk + */ +public class PseudocodeUtil { + + public static Pseudocode generatePseudocode(@NotNull JetDeclaration declaration, @NotNull final BindingContext bindingContext) { + BindingTrace mockTrace = new BindingTrace() { + @Override + public BindingContext getBindingContext() { + return bindingContext; + } + + @Override + public void record(WritableSlice slice, K key, V value) { + } + + @Override + public void record(WritableSlice slice, K key) { + } + + @Override + public V get(ReadOnlySlice slice, K key) { + return bindingContext.get(slice, key); + } + + @NotNull + @Override + public Collection getKeys(WritableSlice slice) { + return bindingContext.getKeys(slice); + } + + @Override + public void report(@NotNull Diagnostic diagnostic) { + } + }; + return new JetControlFlowProcessor(mockTrace).generatePseudocode(declaration); + } + + +} diff --git a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java index 17aa231055b..faddb91de9e 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java @@ -29,15 +29,10 @@ import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; import org.jetbrains.jet.lang.cfg.pseudocode.*; -import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; -import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; -import org.jetbrains.jet.util.slicedmap.WritableSlice; import java.io.File; import java.io.FileNotFoundException; @@ -80,41 +75,12 @@ public class JetControlFlowTest extends JetLiteFixture { final Map data = new LinkedHashMap(); AnalyzeExhaust analyzeExhaust = JetTestUtils.analyzeFile(file); List declarations = file.getDeclarations(); - final BindingContext bindingContext = analyzeExhaust.getBindingContext(); - - BindingTrace mockTrace = new BindingTrace() { - @Override - public BindingContext getBindingContext() { - return bindingContext; - } - - @Override - public void record(WritableSlice slice, K key, V value) { - } - - @Override - public void record(WritableSlice slice, K key) { - } - - @Override - public V get(ReadOnlySlice slice, K key) { - return bindingContext.get(slice, key); - } - - @NotNull - @Override - public Collection getKeys(WritableSlice slice) { - return bindingContext.getKeys(slice); - } - - @Override - public void report(@NotNull Diagnostic diagnostic) { - } - }; + BindingContext bindingContext = analyzeExhaust.getBindingContext(); for (JetDeclaration declaration : declarations) { - Pseudocode pseudocode = new JetControlFlowProcessor(mockTrace).generatePseudocode(declaration); + Pseudocode pseudocode = PseudocodeUtil.generatePseudocode(declaration, bindingContext); data.put(declaration, pseudocode); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) { + Pseudocode localPseudocode = instruction.getBody(); data.put(localPseudocode.getCorrespondingElement(), localPseudocode); } } @@ -166,7 +132,7 @@ public class JetControlFlowTest extends JetLiteFixture { instructionDump.append("=====================\n"); //check edges directions - Collection instructions = ((PseudocodeImpl)pseudocode).getMutableInstructionList(); + Collection instructions = ((PseudocodeImpl)pseudocode).getAllInstructions(); for (Instruction instruction : instructions) { if (!((InstructionImpl)instruction).isDead()) { for (Instruction nextInstruction : instruction.getNextInstructions()) { @@ -198,7 +164,7 @@ public class JetControlFlowTest extends JetLiteFixture { } public void dfsDump(PseudocodeImpl pseudocode, StringBuilder nodes, StringBuilder edges, Map nodeNames) { - dfsDump(nodes, edges, pseudocode.getMutableInstructionList().get(0), nodeNames); + dfsDump(nodes, edges, pseudocode.getAllInstructions().get(0), nodeNames); } private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map nodeNames) { @@ -260,7 +226,7 @@ public class JetControlFlowTest extends JetLiteFixture { } public void dumpInstructions(PseudocodeImpl pseudocode, @NotNull StringBuilder out) { - List instructions = pseudocode.getMutableInstructionList(); + List instructions = pseudocode.getAllInstructions(); Set remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions()); List labels = pseudocode.getLabels(); List locals = new ArrayList(); @@ -316,7 +282,7 @@ public class JetControlFlowTest extends JetLiteFixture { public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) { int index = count[0]; // instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName); - printEdge(out, nodeToName.get(instruction), nodeToName.get(((PseudocodeImpl)instruction.getBody()).getMutableInstructionList().get(0)), null); + printEdge(out, nodeToName.get(instruction), nodeToName.get(((PseudocodeImpl)instruction.getBody()).getAllInstructions().get(0)), null); visitInstructionWithNext(instruction); } @@ -431,7 +397,7 @@ public class JetControlFlowTest extends JetLiteFixture { int[] count = new int[1]; Map nodeToName = new HashMap(); for (Pseudocode pseudocode : pseudocodes) { - dumpNodes(((PseudocodeImpl)pseudocode).getMutableInstructionList(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions())); + dumpNodes(((PseudocodeImpl)pseudocode).getAllInstructions(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions())); } int i = 0; for (Pseudocode pseudocode : pseudocodes) { @@ -447,7 +413,7 @@ public class JetControlFlowTest extends JetLiteFixture { out.println("subgraph cluster_" + i + " {\n" + "label=\"" + label + "\";\n" + "color=blue;\n"); - dumpEdges(((PseudocodeImpl)pseudocode).getMutableInstructionList(), out, count, nodeToName); + dumpEdges(((PseudocodeImpl)pseudocode).getAllInstructions(), out, count, nodeToName); out.println("}"); i++; } From d1d0722b5a6afdfbe2c87f129624721500282cf4 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 13:36:00 +0400 Subject: [PATCH 11/24] tests for dead code in pseudocode --- compiler/testData/cfg/DeadCode.instructions | 20 ++++++++++++++++++++ compiler/testData/cfg/DeadCode.jet | 4 ++++ 2 files changed, 24 insertions(+) create mode 100644 compiler/testData/cfg/DeadCode.instructions create mode 100644 compiler/testData/cfg/DeadCode.jet diff --git a/compiler/testData/cfg/DeadCode.instructions b/compiler/testData/cfg/DeadCode.instructions new file mode 100644 index 00000000000..ff25e3f0b72 --- /dev/null +++ b/compiler/testData/cfg/DeadCode.instructions @@ -0,0 +1,20 @@ +== test == +fun test() { + throw Exception() + test() +} +--------------------- +l0: + NEXT:[r(Exception)] PREV:[] + r(Exception) NEXT:[r(Exception())] PREV:[] + r(Exception()) NEXT:[jmp(error)] PREV:[r(Exception)] + jmp(error) NEXT:[] PREV:[r(Exception())] +- r(test) NEXT:[r(test())] PREV:[] +- r(test()) NEXT:[] PREV:[] +l1: + NEXT:[] PREV:[] +error: + NEXT:[] PREV:[jmp(error)] +sink: + NEXT:[] PREV:[, ] +===================== diff --git a/compiler/testData/cfg/DeadCode.jet b/compiler/testData/cfg/DeadCode.jet new file mode 100644 index 00000000000..6182d2dcd18 --- /dev/null +++ b/compiler/testData/cfg/DeadCode.jet @@ -0,0 +1,4 @@ +fun test() { + throw Exception() + test() +} \ No newline at end of file From cdcedbe6ed2ec324f1c8b31ff0ba0b5a4373febe Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 14:58:38 +0400 Subject: [PATCH 12/24] all traverse pseudocode methods made static --- .../lang/cfg/JetFlowInformationProvider.java | 14 +- ...raverser.java => PseudocodeTraverser.java} | 123 +++++++++--------- .../jetbrains/jet/lang/cfg/data/Edges.java | 66 ++++++++++ .../jet/lang/cfg/data/InstructionData.java | 48 ++----- .../jet/lang/cfg/data/PseudocodeData.java | 115 ++++++++-------- .../lang/cfg/pseudocode/PseudocodeUtil.java | 1 - 6 files changed, 206 insertions(+), 161 deletions(-) rename compiler/frontend/src/org/jetbrains/jet/lang/cfg/{JetControlFlowGraphTraverser.java => PseudocodeTraverser.java} (57%) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index c643fe1a65b..71ddd8e3e44 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -38,6 +38,7 @@ import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetMainDetector; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -62,7 +63,7 @@ public class JetFlowInformationProvider { subroutine = declaration; this.trace = trace; pseudocode = new JetControlFlowProcessor(trace).generatePseudocode(declaration); - pseudocodeData = new PseudocodeData(pseudocode, trace); + pseudocodeData = new PseudocodeData(pseudocode, trace.getBindingContext()); } private void collectReturnExpressions(@NotNull final Collection returnedExpressions) { @@ -195,7 +196,7 @@ public class JetFlowInformationProvider { VariableDescriptor variableDescriptor = pseudocodeData.extractVariableDescriptorIfAny(instruction, true); if (variableDescriptor == null) return; if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return; - InstructionData.EdgesData variableInitializers = instructionData.getInitializersMap().get( + Edges variableInitializers = instructionData.getInitializersMap().get( variableDescriptor); if (variableInitializers == null) return; if (instruction instanceof ReadValueInstruction) { @@ -394,7 +395,7 @@ public class JetFlowInformationProvider { private void recordInitializedVariables(DeclarationData declarationData, InstructionData instructionData) { for (VariableDescriptor variable : declarationData.usedVariables) { if (variable instanceof PropertyDescriptor && declarationData.declaredVariables.contains(variable)) { - InstructionData.EdgesData variableInitializers = instructionData.getInitializersMap().get(variable); + Edges variableInitializers = instructionData.getInitializersMap().get(variable); if (variableInitializers == null) return; trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitializers.getIn().isInitialized()); } @@ -411,7 +412,7 @@ public class JetFlowInformationProvider { VariableDescriptor variableDescriptor = pseudocodeData.extractVariableDescriptorIfAny(instruction, false); if (variableDescriptor == null || !declarationData.declaredVariables.contains(variableDescriptor) || !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return; - InstructionData.EdgesData statusEdgesData = instructionData.getUseStatusMap().get(variableDescriptor); + Edges statusEdgesData = instructionData.getUseStatusMap().get(variableDescriptor); VariableUseStatus variableUseStatus = statusEdgesData != null ? statusEdgesData.getIn() : null; if (instruction instanceof WriteValueInstruction) { if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return; @@ -487,10 +488,9 @@ public class JetFlowInformationProvider { public void markUnusedLiteralsInBlock() { assert pseudocode != null; - JetControlFlowGraphTraverser traverser = JetControlFlowGraphTraverser.create(pseudocode, true, true); - traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { + PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { @Override - public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { + public void execute(@NotNull Instruction instruction) { if (!(instruction instanceof ReadValueInstruction)) return; JetElement element = ((ReadValueInstruction) instruction).getElement(); if (!(element instanceof JetFunctionLiteralExpression diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java similarity index 57% rename from compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java rename to compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index 874f163e514..54ce272fa1f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -19,79 +19,71 @@ package org.jetbrains.jet.lang.cfg; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.data.Edges; import org.jetbrains.jet.lang.cfg.pseudocode.*; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; /** * @author svtk */ -public class JetControlFlowGraphTraverser { - private final Pseudocode pseudocode; - private final boolean lookInside; - private final boolean directOrder; - private final Map> dataMap = Maps.newLinkedHashMap(); - - public static JetControlFlowGraphTraverser create(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) { - return new JetControlFlowGraphTraverser(pseudocode, lookInside, straightDirection); - } - - private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean directOrder) { - this.pseudocode = pseudocode; - this.lookInside = lookInside; - this.directOrder = directOrder; - } - +public class PseudocodeTraverser { @NotNull - private Instruction getStartInstruction(@NotNull Pseudocode pseudocode) { + private static Instruction getStartInstruction(@NotNull Pseudocode pseudocode, boolean directOrder) { return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } - @NotNull - public Map> getDataMap() { - return dataMap; - } - - public void collectInformationFromInstructionGraph( + public static Map> collectInformationFromInstructionGraph( + boolean lookInside, + boolean directOrder, + @NotNull Pseudocode pseudocode, @NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy) { - initializeDataMap(pseudocode, initialDataValue); - dataMap.put(getStartInstruction(pseudocode), - Pair.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); + Map> dataMap = Maps.newLinkedHashMap(); + initializeDataMap(lookInside, dataMap, pseudocode, initialDataValue); + dataMap.put(getStartInstruction(pseudocode, directOrder), + Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); boolean[] changed = new boolean[1]; changed[0] = true; while (changed[0]) { changed[0] = false; - traverseSubGraph(pseudocode, instructionDataMergeStrategy, Collections.emptyList(), changed, false); + traverseSubGraph(lookInside, pseudocode, dataMap, instructionDataMergeStrategy, Collections.emptyList(), directOrder, changed, false); } + return dataMap; } - private void initializeDataMap( - @NotNull Pseudocode pseudocode, + private static void initializeDataMap( + boolean lookInside, + @NotNull Map> dataMap, @NotNull Pseudocode pseudocode, @NotNull D initialDataValue) { List instructions = pseudocode.getInstructions(); - Pair initialPair = Pair.create(initialDataValue, initialDataValue); + Edges initialEdge = Edges.create(initialDataValue, initialDataValue); for (Instruction instruction : instructions) { - dataMap.put(instruction, initialPair); + dataMap.put(instruction, initialEdge); if (lookInside && instruction instanceof LocalDeclarationInstruction) { - initializeDataMap(((LocalDeclarationInstruction) instruction).getBody(), initialDataValue); + initializeDataMap(lookInside, dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue); } } } - private void traverseSubGraph( + private static void traverseSubGraph( + boolean lookInside, @NotNull Pseudocode pseudocode, + @NotNull Map> dataMap, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, @NotNull Collection previousSubGraphInstructions, + boolean directOrder, boolean[] changed, boolean isLocal) { List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); - Instruction startInstruction = getStartInstruction(pseudocode); + Instruction startInstruction = getStartInstruction(pseudocode, directOrder); for (Instruction instruction : instructions) { boolean isStart = directOrder ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; @@ -110,27 +102,27 @@ public class JetControlFlowGraphTraverser { if (lookInside && instruction instanceof LocalDeclarationInstruction) { Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); - traverseSubGraph(subroutinePseudocode, instructionDataMergeStrategy, previousInstructions, changed, true); + traverseSubGraph(lookInside, subroutinePseudocode, dataMap ,instructionDataMergeStrategy, previousInstructions, directOrder, changed, true); Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); - Pair previousValue = dataMap.get(instruction); - Pair newValue = dataMap.get(lastInstruction); + Edges previousValue = dataMap.get(instruction); + Edges newValue = dataMap.get(lastInstruction); if (!previousValue.equals(newValue)) { changed[0] = true; dataMap.put(instruction, newValue); } continue; } - Pair previousDataValue = dataMap.get(instruction); + Edges previousDataValue = dataMap.get(instruction); Collection incomingEdgesData = Sets.newHashSet(); for (Instruction previousInstruction : allPreviousInstructions) { - Pair previousData = dataMap.get(previousInstruction); + Edges previousData = dataMap.get(previousInstruction); if (previousData != null) { - incomingEdgesData.add(previousData.getSecond()); + incomingEdgesData.add(previousData.out); } } - Pair mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData); + Edges mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData); if (!mergedData.equals(previousDataValue)) { changed[0] = true; dataMap.put(instruction, mergedData); @@ -138,13 +130,28 @@ public class JetControlFlowGraphTraverser { } } - public void traverseAndAnalyzeInstructionGraph( - @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { - traverseAndAnalyzeInstructionGraph(pseudocode, instructionDataAnalyzeStrategy); - } - - private void traverseAndAnalyzeInstructionGraph( + public static void traverseAndAnalyzeInstructionGraph( @NotNull Pseudocode pseudocode, + boolean directOrder, + SimpleInstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { + List instructions = pseudocode.getInstructions(); + if (!directOrder) { + instructions = Lists.newArrayList(instructions); + Collections.reverse(instructions); + } + for (Instruction instruction : instructions) { + if (instruction instanceof LocalDeclarationInstruction) { + traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionDataAnalyzeStrategy); + } + instructionDataAnalyzeStrategy.execute(instruction); + } + } + + public static void traverseAndAnalyzeInstructionGraph( + boolean lookInside, + @NotNull Pseudocode pseudocode, + @NotNull Map> dataMap, + boolean directOrder, @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { List instructions = pseudocode.getInstructions(); if (!directOrder) { @@ -153,24 +160,22 @@ public class JetControlFlowGraphTraverser { } for (Instruction instruction : instructions) { if (lookInside && instruction instanceof LocalDeclarationInstruction) { - traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy); + traverseAndAnalyzeInstructionGraph(lookInside, ((LocalDeclarationInstruction) instruction).getBody(), dataMap, directOrder, instructionDataAnalyzeStrategy); } - Pair pair = dataMap.get(instruction); - instructionDataAnalyzeStrategy.execute(instruction, - pair != null ? pair.getFirst() : null, - pair != null ? pair.getSecond() : null); + Edges edges = dataMap.get(instruction); + instructionDataAnalyzeStrategy.execute(instruction, edges != null ? edges.in : null, edges != null ? edges.out : null); } } - public D getResultInfo() { - return dataMap.get(pseudocode.getExitInstruction()).getFirst(); - } - public interface InstructionDataMergeStrategy { - Pair execute(@NotNull Instruction instruction, @NotNull Collection incomingEdgesData); + Edges execute(@NotNull Instruction instruction, @NotNull Collection incomingEdgesData); } public interface InstructionDataAnalyzeStrategy { void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData); } + + public interface SimpleInstructionDataAnalyzeStrategy { + void execute(@NotNull Instruction instruction); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java new file mode 100644 index 00000000000..519a491743e --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; + +import org.jetbrains.annotations.NotNull; + +/** +* @author svtk +*/ +public class Edges { + public final T in; + public final T out; + + Edges(@NotNull T in, @NotNull T out) { + this.in = in; + this.out = out; + } + + public static Edges create(@NotNull T in, @NotNull T out) { + return new Edges(in, out); + } + + @NotNull + public T getIn() { + return in; + } + + @NotNull + public T getOut() { + return out; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Edges)) return false; + + Edges edges = (Edges) o; + + if (in != null ? !in.equals(edges.in) : edges.in != null) return false; + if (out != null ? !out.equals(edges.out) : edges.out != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = in != null ? in.hashCode() : 0; + result = 31 * result + (out != null ? out.hashCode() : 0); + return result; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java index ec77df1997d..2a0df4cd178 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java @@ -31,62 +31,38 @@ public class InstructionData { public final Instruction instruction; public final PseudocodeData pseudocodeData; - private final Map> initializersMap = Maps.newHashMap(); - private final Map> useStatusMap = Maps.newHashMap(); + private final Map> initializersMap = Maps.newHashMap(); + private final Map> useStatusMap = Maps.newHashMap(); public InstructionData(@NotNull PseudocodeData data, @NotNull Instruction instruction, - @NotNull Pair, Map> pairOfVariableInitializersMap, - @NotNull Pair, Map> pairOfVariableStatusMap) { + @NotNull Edges> pairOfVariableInitializersMap, + @NotNull Edges> pairOfVariableStatusMap) { pseudocodeData = data; this.instruction = instruction; - for (Map.Entry entry : pairOfVariableInitializersMap.second.entrySet()) { + for (Map.Entry entry : pairOfVariableInitializersMap.out.entrySet()) { VariableDescriptor variableDescriptor = entry.getKey(); - VariableInitializers in = pairOfVariableInitializersMap.first.get(variableDescriptor); + VariableInitializers in = pairOfVariableInitializersMap.in.get(variableDescriptor); VariableInitializers out = entry.getValue(); - initializersMap.put(variableDescriptor, EdgesData.create(in, out)); + initializersMap.put(variableDescriptor, Edges.create(in, out)); } - for (Map.Entry entry : pairOfVariableStatusMap.second.entrySet()) { + for (Map.Entry entry : pairOfVariableStatusMap.out.entrySet()) { VariableDescriptor variableDescriptor = entry.getKey(); - VariableUseStatus in = pairOfVariableStatusMap.first.get(variableDescriptor); + VariableUseStatus in = pairOfVariableStatusMap.in.get(variableDescriptor); VariableUseStatus out = entry.getValue(); if (in == null || out == null) continue; - useStatusMap.put(variableDescriptor, EdgesData.create(in, out)); + useStatusMap.put(variableDescriptor, Edges.create(in, out)); } } @NotNull - public Map> getInitializersMap() { + public Map> getInitializersMap() { return initializersMap; } @NotNull - public Map> getUseStatusMap() { + public Map> getUseStatusMap() { return useStatusMap; } - - public static class EdgesData { - private final T in; - private final T out; - - private EdgesData(@NotNull T in, @NotNull T out) { - this.in = in; - this.out = out; - } - - private static EdgesData create(@NotNull T in, @NotNull T out) { - return new EdgesData(in, out); - } - - @NotNull - public T getIn() { - return in; - } - - @NotNull - public T getOut() { - return out; - } - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java index ccb6173d932..38d7a54a0d0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java @@ -19,10 +19,9 @@ package org.jetbrains.jet.lang.cfg.data; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.cfg.JetControlFlowGraphTraverser; +import org.jetbrains.jet.lang.cfg.PseudocodeTraverser; import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; @@ -31,7 +30,6 @@ import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; -import org.jetbrains.jet.lang.resolve.BindingTrace; import java.util.*; @@ -42,29 +40,38 @@ public class PseudocodeData { private final Pseudocode pseudocode; private final Map instructionDataMap = Maps.newLinkedHashMap(); private final Map declarationDataMap = Maps.newLinkedHashMap(); - private final BindingTrace trace; - public PseudocodeData(@NotNull Pseudocode pseudocode, @NotNull BindingTrace trace) { + //private final Map> declaredVariablesInEachDeclaration; + //private final Map> usedVariablesInEachDeclaration; + + private final BindingContext bindingContext; + + public PseudocodeData(@NotNull Pseudocode pseudocode, @NotNull BindingContext bindingContext) { this.pseudocode = pseudocode; - this.trace = trace; + this.bindingContext = bindingContext; collectDeclarationData(pseudocode); DeclarationData declarationData = declarationDataMap.get(pseudocode); - final Map, Map>> variableInitializersMap = + final Map>> variableInitializersMap = collectVariableInitializers(pseudocode, declarationData); - final Map, Map>> variableStatusMap = + final Map>> variableStatusMap = collectVariableStatusData(); - JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph( - new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction, Void enterData, Void exitData) { - instructionDataMap.put(instruction, - new InstructionData(PseudocodeData.this, instruction, variableInitializersMap.get(instruction), - variableStatusMap.get(instruction))); - } - }); + + PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, + new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { + @Override + public void execute(@NotNull Instruction instruction) { + instructionDataMap.put(instruction, + new InstructionData(PseudocodeData.this, + instruction, + variableInitializersMap + .get(instruction), + variableStatusMap + .get(instruction))); + } + }); } @NotNull @@ -126,64 +133,59 @@ public class PseudocodeData { private Set collectUsedVariables(@NotNull Pseudocode pseudocode) { final Set usedVariables = Sets.newHashSet(); - JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); - if (variableDescriptor != null) { - usedVariables.add(variableDescriptor); - } - } - }); + PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, + new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { + @Override + public void execute(@NotNull Instruction instruction) { + VariableDescriptor variableDescriptor = + extractVariableDescriptorIfAny(instruction, false); + if (variableDescriptor != null) { + usedVariables.add(variableDescriptor); + } + } + }); return usedVariables; } private Set collectDeclaredVariables(@NotNull Pseudocode pseudocode) { final Set declaredVariables = Sets.newHashSet(); - JetControlFlowGraphTraverser.create(pseudocode, false, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { - if (instruction instanceof VariableDeclarationInstruction) { - JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); - DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement); - if (descriptor != null) { - assert descriptor instanceof VariableDescriptor; - declaredVariables.add((VariableDescriptor) descriptor); - } + for (Instruction instruction : pseudocode.getInstructions()) { + if (instruction instanceof VariableDeclarationInstruction) { + JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement); + if (descriptor != null) { + assert descriptor instanceof VariableDescriptor; + declaredVariables.add((VariableDescriptor) descriptor); } } - }); + } return declaredVariables; } // variable initializers - private Map, Map>> collectVariableInitializers( + private Map>> collectVariableInitializers( Pseudocode pseudocode, DeclarationData data) { - - JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, false, true); - final Map initialMapForStartInstruction = prepareInitialMapForStartInstruction(data.usedVariables, data.declaredVariables); - traverser.collectInformationFromInstructionGraph(Collections.emptyMap(), initialMapForStartInstruction, - new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { + Map>> result = + PseudocodeTraverser.collectInformationFromInstructionGraph(false, true, pseudocode, Collections.emptyMap(), initialMapForStartInstruction, + new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override - public Pair, Map> execute( + public Edges> execute( @NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { Map enterInstructionData = mergeIncomingEdgesData(incomingEdgesData); Map exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); - return Pair.create(enterInstructionData, exitInstructionData); + return Edges.create(enterInstructionData, exitInstructionData); } }); - Map, Map>> result = - traverser.getDataMap(); for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { Pseudocode localPseudocode = localDeclarationInstruction.getBody(); - Map, Map>> initializersForLocalDeclaration = + Map>> initializersForLocalDeclaration = collectVariableInitializers(localPseudocode, declarationDataMap.get(localPseudocode)); for (Instruction instruction : initializersForLocalDeclaration.keySet()) { @@ -267,17 +269,15 @@ public class PseudocodeData { // variable use - private Map, Map>> collectVariableStatusData() { - JetControlFlowGraphTraverser> traverser = - JetControlFlowGraphTraverser.create(pseudocode, true, false); + private Map>> collectVariableStatusData() { Map sinkInstructionData = Maps.newHashMap(); for (VariableDescriptor usedVariable : declarationDataMap.get(pseudocode).usedVariables) { sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); } - traverser.collectInformationFromInstructionGraph(Collections.emptyMap(), sinkInstructionData, - new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { + return PseudocodeTraverser.collectInformationFromInstructionGraph(true, false, pseudocode, Collections.emptyMap(), sinkInstructionData, + new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override - public Pair, Map> execute(@NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { + public Edges> execute(@NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { Map enterResult = Maps.newHashMap(); for (Map edgeData : incomingEdgesData) { for (Map.Entry entry : edgeData.entrySet()) { @@ -288,7 +288,7 @@ public class PseudocodeData { } VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); if (variableDescriptor == null || (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) { - return Pair.create(enterResult, enterResult); + return Edges.create(enterResult, enterResult); } Map exitResult = Maps.newHashMap(enterResult); if (instruction instanceof ReadValueInstruction) { @@ -307,10 +307,9 @@ public class PseudocodeData { exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN); } } - return Pair.create(enterResult, exitResult); + return Edges.create(enterResult, exitResult); } }); - return traverser.getDataMap(); } // Util methods @@ -327,7 +326,7 @@ public class PseudocodeData { else if (instruction instanceof VariableDeclarationInstruction) { element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); } - return BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), element, onlyReference); + return BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, element, onlyReference); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java index 3612cc1a997..f82ce6c46d6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java @@ -65,5 +65,4 @@ public class PseudocodeUtil { return new JetControlFlowProcessor(mockTrace).generatePseudocode(declaration); } - } From 8acfa20a0271c1a2e32aba68b8541f54f742abda Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 16:30:50 +0400 Subject: [PATCH 13/24] lazy computing of pseudocode variables data no need in special 'data' classes --- .../lang/cfg/JetFlowInformationProvider.java | 114 ++++--- .../jet/lang/cfg/PseudocodeTraverser.java | 57 +++- ...Data.java => PseudocodeVariablesData.java} | 300 ++++++++++-------- .../jet/lang/cfg/data/DeclarationData.java | 42 --- .../jetbrains/jet/lang/cfg/data/Edges.java | 66 ---- .../jet/lang/cfg/data/InstructionData.java | 68 ---- .../lang/cfg/data/VariableInitializers.java | 100 ------ .../jet/lang/cfg/data/VariableUseStatus.java | 40 --- .../lang/cfg/pseudocode/PseudocodeUtil.java | 18 ++ 9 files changed, 289 insertions(+), 516 deletions(-) rename compiler/frontend/src/org/jetbrains/jet/lang/cfg/{data/PseudocodeData.java => PseudocodeVariablesData.java} (50%) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 71ddd8e3e44..a271bf70c6f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -23,8 +23,10 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.cfg.data.*; import org.jetbrains.jet.lang.cfg.pseudocode.*; +import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges; +import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitializers; +import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseStatus; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; @@ -37,10 +39,7 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetMainDetector; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE; @@ -53,7 +52,7 @@ public class JetFlowInformationProvider { private final JetDeclaration subroutine; private final Pseudocode pseudocode; - private final PseudocodeData pseudocodeData; + private final PseudocodeVariablesData pseudocodeData; private BindingTrace trace; public JetFlowInformationProvider( @@ -63,7 +62,7 @@ public class JetFlowInformationProvider { subroutine = declaration; this.trace = trace; pseudocode = new JetControlFlowProcessor(trace).generatePseudocode(declaration); - pseudocodeData = new PseudocodeData(pseudocode, trace.getBindingContext()); + pseudocodeData = new PseudocodeVariablesData(pseudocode, trace.getBindingContext()); } private void collectReturnExpressions(@NotNull final Collection returnedExpressions) { @@ -120,15 +119,14 @@ public class JetFlowInformationProvider { }); } } - + public void checkDefiniteReturn(final @NotNull JetType expectedReturnType) { assert subroutine instanceof JetDeclarationWithBody; JetDeclarationWithBody function = (JetDeclarationWithBody) subroutine; - assert function instanceof JetDeclaration; JetExpression bodyExpression = function.getBodyExpression(); if (bodyExpression == null) return; - + List returnedExpressions = Lists.newArrayList(); collectReturnExpressions(returnedExpressions); @@ -140,7 +138,7 @@ public class JetFlowInformationProvider { trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType)); } final boolean blockBody = function.hasBlockBody(); - + final Set rootUnreachableElements = collectUnreachableCode(); for (JetElement element : rootUnreachableElements) { trace.report(UNREACHABLE_CODE.on(element)); @@ -189,49 +187,53 @@ public class JetFlowInformationProvider { final Collection varWithValReassignErrorGenerated = Sets.newHashSet(); final boolean processClassOrObject = subroutine instanceof JetClassOrObject; - pseudocodeData.traverseInstructionsGraph(true, true, new PseudocodeData.TraverseInstructionGraphStrategy() { + Map>> initializers = pseudocodeData.getVariableInitializers(); + final Set declaredVariables = pseudocodeData.getDeclaredVariables(pseudocode); + PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, initializers, true, new PseudocodeTraverser.InstructionDataAnalyzeStrategy>() { @Override - public void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData) { - //todo move to util - VariableDescriptor variableDescriptor = pseudocodeData.extractVariableDescriptorIfAny(instruction, true); + public void execute(@NotNull Instruction instruction, + @Nullable Map in, + @Nullable Map out) { + assert in != null && out != null; + VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, + trace.getBindingContext()); if (variableDescriptor == null) return; if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return; - Edges variableInitializers = instructionData.getInitializersMap().get( - variableDescriptor); - if (variableInitializers == null) return; + VariableInitializers outInitializers = out.get(variableDescriptor); if (instruction instanceof ReadValueInstruction) { JetElement element = ((ReadValueInstruction) instruction).getElement(); boolean error = checkBackingField(variableDescriptor, element); - if (!error && declarationData.declaredVariables.contains(variableDescriptor)) { - checkIsInitialized(variableDescriptor, element, variableInitializers.getOut(), varWithUninitializedErrorGenerated); + if (!error && declaredVariables.contains(variableDescriptor)) { + checkIsInitialized(variableDescriptor, element, outInitializers, varWithUninitializedErrorGenerated); } return; } JetElement element = ((WriteValueInstruction) instruction).getlValue(); boolean error = checkBackingField(variableDescriptor, element); if (!(element instanceof JetExpression)) return; + VariableInitializers inInitializers = in.get(variableDescriptor); if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration - error = checkValReassignment(variableDescriptor, (JetExpression) element, variableInitializers.getIn(), varWithValReassignErrorGenerated); + error = checkValReassignment(variableDescriptor, (JetExpression) element, inInitializers, varWithValReassignErrorGenerated); } if (!error && processClassOrObject) { - error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, variableInitializers.getIn(), variableInitializers.getOut()); + error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, inInitializers, outInitializers); } if (!error && processClassOrObject) { - checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, variableInitializers.getIn(), variableInitializers.getOut()); + checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, inInitializers, outInitializers); } } }); Pseudocode pseudocode = pseudocodeData.getPseudocode(); - recordInitializedVariables(pseudocodeData.getDeclarationData(pseudocode), pseudocodeData.getResultInfo(pseudocode)); + recordInitializedVariables(pseudocode, initializers); for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) { - recordInitializedVariables(pseudocodeData.getDeclarationData(instruction.getBody()), pseudocodeData.getResultInfo(instruction.getBody())); + recordInitializedVariables(instruction.getBody(), initializers); } } - private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, - @NotNull JetElement element, - @NotNull VariableInitializers variableInitializers, + private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, + @NotNull JetElement element, + @NotNull VariableInitializers variableInitializers, @NotNull Collection varWithUninitializedErrorGenerated) { if (!(element instanceof JetSimpleNameExpression)) return; @@ -244,7 +246,8 @@ public class JetFlowInformationProvider { if (!isInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) { varWithUninitializedErrorGenerated.add(variableDescriptor); if (variableDescriptor instanceof ValueParameterDescriptor) { - trace.report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element, (ValueParameterDescriptor) variableDescriptor)); + trace.report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element, + (ValueParameterDescriptor) variableDescriptor)); } else { trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor)); @@ -252,9 +255,9 @@ public class JetFlowInformationProvider { } } - private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, - @NotNull JetExpression expression, - @NotNull VariableInitializers enterInitializers, + private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, + @NotNull JetExpression expression, + @NotNull VariableInitializers enterInitializers, @NotNull Collection varWithValReassignErrorGenerated) { boolean isInitializedNotHere = enterInitializers.isInitialized(); Set possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers(); @@ -304,7 +307,7 @@ public class JetFlowInformationProvider { } return false; } - + private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) { if (!enterInitializers.isDeclared() && !exitInitializers.isDeclared() && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) { trace.report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, variableDescriptor)); @@ -312,7 +315,7 @@ public class JetFlowInformationProvider { } return false; } - + private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) { if (variableDescriptor instanceof PropertyDescriptor && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) { if (!variableDescriptor.isVar()) return false; @@ -392,12 +395,15 @@ public class JetFlowInformationProvider { return false; } - private void recordInitializedVariables(DeclarationData declarationData, InstructionData instructionData) { - for (VariableDescriptor variable : declarationData.usedVariables) { - if (variable instanceof PropertyDescriptor && declarationData.declaredVariables.contains(variable)) { - Edges variableInitializers = instructionData.getInitializersMap().get(variable); + private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map>> initializersMap) { + Edges> initializers = initializersMap.get(pseudocode.getExitInstruction()); + Set usedVariables = pseudocodeData.getUsedVariables(pseudocode); + Set declaredVariables = pseudocodeData.getDeclaredVariables(pseudocode); + for (VariableDescriptor variable : usedVariables) { + if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) { + VariableInitializers variableInitializers = initializers.in.get(variable); if (variableInitializers == null) return; - trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitializers.getIn().isInitialized()); + trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitializers.isInitialized()); } } } @@ -406,14 +412,20 @@ public class JetFlowInformationProvider { // "Unused variable" & "unused value" analyses public void markUnusedVariables() { - pseudocodeData.traverseInstructionsGraph(true, false, new PseudocodeData.TraverseInstructionGraphStrategy() { + Map>> variableStatusData = pseudocodeData.getVariableStatusData(); + PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, variableStatusData, false, new PseudocodeTraverser.InstructionDataAnalyzeStrategy>() { @Override - public void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData) { - VariableDescriptor variableDescriptor = pseudocodeData.extractVariableDescriptorIfAny(instruction, false); - if (variableDescriptor == null || !declarationData.declaredVariables.contains(variableDescriptor) || + public void execute(@NotNull Instruction instruction, + @Nullable Map in, + @Nullable Map out) { + + assert in != null && out != null; + Set declaredVariables = pseudocodeData.getDeclaredVariables(instruction.getOwner()); + VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, + trace.getBindingContext()); + if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) || !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return; - Edges statusEdgesData = instructionData.getUseStatusMap().get(variableDescriptor); - VariableUseStatus variableUseStatus = statusEdgesData != null ? statusEdgesData.getIn() : null; + VariableUseStatus variableUseStatus = in.get(variableDescriptor); if (instruction instanceof WriteValueInstruction) { if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return; JetElement element = ((WriteValueInstruction) instruction).getElement(); @@ -480,19 +492,20 @@ public class JetFlowInformationProvider { } }); - } //////////////////////////////////////////////////////////////////////////////// // "Unused literals" in block - + public void markUnusedLiteralsInBlock() { assert pseudocode != null; - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { + PseudocodeTraverser.traverseAndAnalyzeInstructionGraph( + pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { @Override public void execute(@NotNull Instruction instruction) { if (!(instruction instanceof ReadValueInstruction)) return; - JetElement element = ((ReadValueInstruction) instruction).getElement(); + JetElement element = + ((ReadValueInstruction) instruction).getElement(); if (!(element instanceof JetFunctionLiteralExpression || element instanceof JetConstantExpression || element instanceof JetStringTemplateExpression @@ -503,7 +516,8 @@ public class JetFlowInformationProvider { if (parent instanceof JetBlockExpression) { if (!JetPsiUtil.isImplicitlyUsed(element)) { if (element instanceof JetFunctionLiteralExpression) { - trace.report(Errors.UNUSED_FUNCTION_LITERAL.on((JetFunctionLiteralExpression) element)); + trace.report(Errors.UNUSED_FUNCTION_LITERAL + .on((JetFunctionLiteralExpression) element)); } else { trace.report(Errors.UNUSED_EXPRESSION.on(element)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index 54ce272fa1f..e8010b4d31a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -21,7 +21,6 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.cfg.data.Edges; import org.jetbrains.jet.lang.cfg.pseudocode.*; import java.util.Collection; @@ -134,11 +133,7 @@ public class PseudocodeTraverser { @NotNull Pseudocode pseudocode, boolean directOrder, SimpleInstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { - List instructions = pseudocode.getInstructions(); - if (!directOrder) { - instructions = Lists.newArrayList(instructions); - Collections.reverse(instructions); - } + List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); for (Instruction instruction : instructions) { if (instruction instanceof LocalDeclarationInstruction) { traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionDataAnalyzeStrategy); @@ -153,11 +148,7 @@ public class PseudocodeTraverser { @NotNull Map> dataMap, boolean directOrder, @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { - List instructions = pseudocode.getInstructions(); - if (!directOrder) { - instructions = Lists.newArrayList(instructions); - Collections.reverse(instructions); - } + List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); for (Instruction instruction : instructions) { if (lookInside && instruction instanceof LocalDeclarationInstruction) { traverseAndAnalyzeInstructionGraph(lookInside, ((LocalDeclarationInstruction) instruction).getBody(), dataMap, directOrder, instructionDataAnalyzeStrategy); @@ -178,4 +169,48 @@ public class PseudocodeTraverser { public interface SimpleInstructionDataAnalyzeStrategy { void execute(@NotNull Instruction instruction); } + + public static class Edges { + public final T in; + public final T out; + + Edges(@NotNull T in, @NotNull T out) { + this.in = in; + this.out = out; + } + + public static Edges create(@NotNull T in, @NotNull T out) { + return new Edges(in, out); + } + + @NotNull + public T getIn() { + return in; + } + + @NotNull + public T getOut() { + return out; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Edges)) return false; + + Edges edges = (Edges) o; + + if (in != null ? !in.equals(edges.in) : edges.in != null) return false; + if (out != null ? !out.equals(edges.out) : edges.out != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = in != null ? in.hashCode() : 0; + result = 31 * result + (out != null ? out.hashCode() : 0); + return result; + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java similarity index 50% rename from compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java rename to compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index 38d7a54a0d0..9247f6d1189 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -14,14 +14,13 @@ * limitations under the License. */ -package org.jetbrains.jet.lang.cfg.data; +package org.jetbrains.jet.lang.cfg; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.cfg.PseudocodeTraverser; +import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges; import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; @@ -29,49 +28,28 @@ import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; /** * @author svtk */ -public class PseudocodeData { +public class PseudocodeVariablesData { private final Pseudocode pseudocode; - private final Map instructionDataMap = Maps.newLinkedHashMap(); - private final Map declarationDataMap = Maps.newLinkedHashMap(); - - //private final Map> declaredVariablesInEachDeclaration; - //private final Map> usedVariablesInEachDeclaration; - private final BindingContext bindingContext; - public PseudocodeData(@NotNull Pseudocode pseudocode, @NotNull BindingContext bindingContext) { + private final Map> declaredVariablesInEachDeclaration = Maps.newHashMap(); + private final Map> usedVariablesInEachDeclaration = Maps.newHashMap(); + + private Map>> variableInitializersMap; + private Map>> variableStatusMap; + + public PseudocodeVariablesData(@NotNull Pseudocode pseudocode, @NotNull BindingContext bindingContext) { this.pseudocode = pseudocode; this.bindingContext = bindingContext; - collectDeclarationData(pseudocode); - - DeclarationData declarationData = declarationDataMap.get(pseudocode); - - final Map>> variableInitializersMap = - collectVariableInitializers(pseudocode, declarationData); - final Map>> variableStatusMap = - collectVariableStatusData(); - - - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, - new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction) { - instructionDataMap.put(instruction, - new InstructionData(PseudocodeData.this, - instruction, - variableInitializersMap - .get(instruction), - variableStatusMap - .get(instruction))); - } - }); } @NotNull @@ -79,98 +57,66 @@ public class PseudocodeData { return pseudocode; } - @NotNull - public Map getInstructionDataMap() { - return instructionDataMap; - } - - @NotNull - public DeclarationData getDeclarationData(Pseudocode pseudocode) { - return declarationDataMap.get(pseudocode); - } - - @NotNull - public InstructionData getResultInfo(Pseudocode pseudocode) { - return instructionDataMap.get(pseudocode.getExitInstruction()); - } - - public void traverseInstructionsGraph(boolean lookInside, boolean straightDirection, - @NotNull TraverseInstructionGraphStrategy traverseInstructionGraphStrategy) { - traverseInstructionsGraph(pseudocode, lookInside, straightDirection, traverseInstructionGraphStrategy); - } - - private void traverseInstructionsGraph(@NotNull Pseudocode pseudocode, - boolean lookInside, - boolean straightDirection, - @NotNull TraverseInstructionGraphStrategy traverseInstructionGraphStrategy) { - List instructions = pseudocode.getInstructions(); - if (!straightDirection) { - instructions = Lists.newArrayList(instructions); - Collections.reverse(instructions); + public Set getUsedVariables(@NotNull Pseudocode pseudocode) { + Set usedVariables = usedVariablesInEachDeclaration.get(pseudocode); + if (usedVariables == null) { + final Set result = Sets.newHashSet(); + PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { + @Override + public void execute(@NotNull Instruction instruction) { + VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, + bindingContext); + if (variableDescriptor != null) { + result.add(variableDescriptor); + } + } + }); + usedVariables = Collections.unmodifiableSet(result); + usedVariablesInEachDeclaration.put(pseudocode, usedVariables); } - for (Instruction instruction : instructions) { - if (lookInside && instruction instanceof LocalDeclarationInstruction) { - traverseInstructionsGraph(((LocalDeclarationInstruction) instruction).getBody(), lookInside, straightDirection, - traverseInstructionGraphStrategy - ); - } - traverseInstructionGraphStrategy.execute(instruction, declarationDataMap.get(pseudocode), instructionDataMap.get(instruction)); - } - } - - public interface TraverseInstructionGraphStrategy { - void execute(@NotNull Instruction instruction, @NotNull DeclarationData declarationData, @NotNull InstructionData instructionData); - } - - private void collectDeclarationData(Pseudocode pseudocode) { - DeclarationData declarationData = new DeclarationData(pseudocode.getCorrespondingElement(), this, collectDeclaredVariables(pseudocode), collectUsedVariables(pseudocode)); - declarationDataMap.put(pseudocode, declarationData); - - for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { - collectDeclarationData(localDeclarationInstruction.getBody()); - } - } - - private Set collectUsedVariables(@NotNull Pseudocode pseudocode) { - final Set usedVariables = Sets.newHashSet(); - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, - new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { - @Override - public void execute(@NotNull Instruction instruction) { - VariableDescriptor variableDescriptor = - extractVariableDescriptorIfAny(instruction, false); - if (variableDescriptor != null) { - usedVariables.add(variableDescriptor); - } - } - }); return usedVariables; } - private Set collectDeclaredVariables(@NotNull Pseudocode pseudocode) { - final Set declaredVariables = Sets.newHashSet(); - for (Instruction instruction : pseudocode.getInstructions()) { - if (instruction instanceof VariableDeclarationInstruction) { - JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); - DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement); - if (descriptor != null) { - assert descriptor instanceof VariableDescriptor; - declaredVariables.add((VariableDescriptor) descriptor); + public Set getDeclaredVariables(@NotNull Pseudocode pseudocode) { + Set declaredVariables = declaredVariablesInEachDeclaration.get(pseudocode); + if (declaredVariables == null) { + declaredVariables = Sets.newHashSet(); + for (Instruction instruction : pseudocode.getInstructions()) { + if (instruction instanceof VariableDeclarationInstruction) { + JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement); + if (descriptor != null) { + assert descriptor instanceof VariableDescriptor; + declaredVariables.add((VariableDescriptor) descriptor); + } } } + declaredVariables = Collections.unmodifiableSet(declaredVariables); + declaredVariablesInEachDeclaration.put(pseudocode, declaredVariables); } return declaredVariables; } // variable initializers - private Map>> collectVariableInitializers( - Pseudocode pseudocode, DeclarationData data) { - final Map initialMapForStartInstruction = prepareInitialMapForStartInstruction(data.usedVariables, data.declaredVariables); + @NotNull + public Map>> getVariableInitializers() { + if (variableInitializersMap == null) { + variableInitializersMap = getVariableInitializers(pseudocode); + } + return variableInitializersMap; + } - Map>> result = - PseudocodeTraverser.collectInformationFromInstructionGraph(false, true, pseudocode, Collections.emptyMap(), initialMapForStartInstruction, - new PseudocodeTraverser.InstructionDataMergeStrategy>() { + @NotNull + private Map>> getVariableInitializers(Pseudocode pseudocode) { + + Set usedVariables = getUsedVariables(pseudocode); + Set declaredVariables = getDeclaredVariables(pseudocode); + final Map initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables); + + Map>> variableInitializersMap = PseudocodeTraverser.collectInformationFromInstructionGraph(false, true, pseudocode, + Collections.emptyMap(), initialMapForStartInstruction, + new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override public Edges> execute( @NotNull Instruction instruction, @@ -185,19 +131,17 @@ public class PseudocodeData { for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { Pseudocode localPseudocode = localDeclarationInstruction.getBody(); - Map>> initializersForLocalDeclaration = - collectVariableInitializers(localPseudocode, declarationDataMap.get(localPseudocode)); + Map>> initializersForLocalDeclaration = getVariableInitializers(localPseudocode); for (Instruction instruction : initializersForLocalDeclaration.keySet()) { //todo - if (!result.containsKey(instruction)) { - result.put(instruction, initializersForLocalDeclaration.get(instruction)); + if (!variableInitializersMap.containsKey(instruction)) { + variableInitializersMap.put(instruction, initializersForLocalDeclaration.get(instruction)); } } - result.putAll(initializersForLocalDeclaration); + variableInitializersMap.putAll(initializersForLocalDeclaration); } - - return result; + return variableInitializersMap; } private Map prepareInitialMapForStartInstruction(Collection usedVariables, Collection declaredVariables) { @@ -240,7 +184,7 @@ public class PseudocodeData { if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) { return enterInstructionData; } - VariableDescriptor variable = extractVariableDescriptorIfAny(instruction, false); + VariableDescriptor variable = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, bindingContext); if (variable == null) { return enterInstructionData; } @@ -269,13 +213,16 @@ public class PseudocodeData { // variable use - private Map>> collectVariableStatusData() { + @NotNull + public Map>> getVariableStatusData() { + if (variableStatusMap == null) { Map sinkInstructionData = Maps.newHashMap(); - for (VariableDescriptor usedVariable : declarationDataMap.get(pseudocode).usedVariables) { + for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) { sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); } - return PseudocodeTraverser.collectInformationFromInstructionGraph(true, false, pseudocode, Collections.emptyMap(), sinkInstructionData, - new PseudocodeTraverser.InstructionDataMergeStrategy>() { + variableStatusMap = PseudocodeTraverser.collectInformationFromInstructionGraph(true, false, pseudocode, + Collections.emptyMap(), sinkInstructionData, + new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override public Edges> execute(@NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { Map enterResult = Maps.newHashMap(); @@ -286,7 +233,7 @@ public class PseudocodeData { enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor))); } } - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); + VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, bindingContext); if (variableDescriptor == null || (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) { return Edges.create(enterResult, enterResult); } @@ -310,23 +257,98 @@ public class PseudocodeData { return Edges.create(enterResult, exitResult); } }); + } + return variableStatusMap; } -// Util methods + public static class VariableInitializers { + private final Set possibleLocalInitializers = Sets.newHashSet(); + private boolean isInitialized; + private boolean isDeclared; - @Nullable - public VariableDescriptor extractVariableDescriptorIfAny(@NotNull Instruction instruction, boolean onlyReference) { - JetElement element = null; - if (instruction instanceof ReadValueInstruction) { - element = ((ReadValueInstruction) instruction).getElement(); + public VariableInitializers(boolean isInitialized) { + this(isInitialized, false); } - else if (instruction instanceof WriteValueInstruction) { - element = ((WriteValueInstruction) instruction).getlValue(); + + public VariableInitializers(boolean isInitialized, boolean isDeclared) { + this.isInitialized = isInitialized; + this.isDeclared = isDeclared; } - else if (instruction instanceof VariableDeclarationInstruction) { - element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + + public VariableInitializers(JetElement element, @Nullable VariableInitializers previous) { + isInitialized = true; + isDeclared = element instanceof JetProperty || (previous != null && previous.isDeclared()); + possibleLocalInitializers.add(element); + } + + public VariableInitializers(Set edgesData) { + isInitialized = true; + isDeclared = true; + for (VariableInitializers edgeData : edgesData) { + if (!edgeData.isInitialized) { + isInitialized = false; + } + if (!edgeData.isDeclared) { + isDeclared = false; + } + possibleLocalInitializers.addAll(edgeData.possibleLocalInitializers); + } + } + + public Set getPossibleLocalInitializers() { + return possibleLocalInitializers; + } + + public boolean isInitialized() { + return isInitialized; + } + + public boolean isDeclared() { + return isDeclared; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof VariableInitializers)) return false; + + VariableInitializers that = (VariableInitializers) o; + + if (isDeclared != that.isDeclared) return false; + if (isInitialized != that.isInitialized) return false; + if (possibleLocalInitializers != null + ? !possibleLocalInitializers.equals(that.possibleLocalInitializers) + : that.possibleLocalInitializers != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = possibleLocalInitializers != null ? possibleLocalInitializers.hashCode() : 0; + result = 31 * result + (isInitialized ? 1 : 0); + result = 31 * result + (isDeclared ? 1 : 0); + return result; } - return BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, element, onlyReference); } + public static enum VariableUseStatus { + LAST_READ(3), + LAST_WRITTEN(2), + ONLY_WRITTEN_NEVER_READ(1), + UNUSED(0); + + private final int importance; + + VariableUseStatus(int importance) { + this.importance = importance; + } + + public VariableUseStatus merge(@Nullable VariableUseStatus variableUseStatus) { + if (variableUseStatus == null || importance > variableUseStatus.importance) return this; + return variableUseStatus; + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java deleted file mode 100644 index f22d47136bc..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/DeclarationData.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; - -import org.jetbrains.jet.lang.descriptors.VariableDescriptor; -import org.jetbrains.jet.lang.psi.JetElement; - -import java.util.Set; - -/** - * @author svtk - */ -public class DeclarationData { - public final JetElement element; - public final PseudocodeData pseudocodeData; - public final Set declaredVariables; - public final Set usedVariables; - - public DeclarationData(JetElement element, - PseudocodeData data, - Set declaredVariables, - Set usedVariables) { - this.element = element; - pseudocodeData = data; - this.declaredVariables = declaredVariables; - this.usedVariables = usedVariables; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java deleted file mode 100644 index 519a491743e..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/Edges.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; - -import org.jetbrains.annotations.NotNull; - -/** -* @author svtk -*/ -public class Edges { - public final T in; - public final T out; - - Edges(@NotNull T in, @NotNull T out) { - this.in = in; - this.out = out; - } - - public static Edges create(@NotNull T in, @NotNull T out) { - return new Edges(in, out); - } - - @NotNull - public T getIn() { - return in; - } - - @NotNull - public T getOut() { - return out; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Edges)) return false; - - Edges edges = (Edges) o; - - if (in != null ? !in.equals(edges.in) : edges.in != null) return false; - if (out != null ? !out.equals(edges.out) : edges.out != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = in != null ? in.hashCode() : 0; - result = 31 * result + (out != null ? out.hashCode() : 0); - return result; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java deleted file mode 100644 index 2a0df4cd178..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/InstructionData.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; - -import com.google.common.collect.Maps; -import com.intellij.openapi.util.Pair; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; -import org.jetbrains.jet.lang.descriptors.VariableDescriptor; - -import java.util.Map; - -/** - * @author svtk - */ -public class InstructionData { - public final Instruction instruction; - public final PseudocodeData pseudocodeData; - - private final Map> initializersMap = Maps.newHashMap(); - private final Map> useStatusMap = Maps.newHashMap(); - - public InstructionData(@NotNull PseudocodeData data, @NotNull Instruction instruction, - @NotNull Edges> pairOfVariableInitializersMap, - @NotNull Edges> pairOfVariableStatusMap) { - pseudocodeData = data; - this.instruction = instruction; - - for (Map.Entry entry : pairOfVariableInitializersMap.out.entrySet()) { - VariableDescriptor variableDescriptor = entry.getKey(); - VariableInitializers in = pairOfVariableInitializersMap.in.get(variableDescriptor); - VariableInitializers out = entry.getValue(); - initializersMap.put(variableDescriptor, Edges.create(in, out)); - } - - for (Map.Entry entry : pairOfVariableStatusMap.out.entrySet()) { - VariableDescriptor variableDescriptor = entry.getKey(); - VariableUseStatus in = pairOfVariableStatusMap.in.get(variableDescriptor); - VariableUseStatus out = entry.getValue(); - if (in == null || out == null) continue; - useStatusMap.put(variableDescriptor, Edges.create(in, out)); - } - } - - @NotNull - public Map> getInitializersMap() { - return initializersMap; - } - - @NotNull - public Map> getUseStatusMap() { - return useStatusMap; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java deleted file mode 100644 index c30cef1a60f..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableInitializers.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; - -import com.google.common.collect.Sets; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetElement; -import org.jetbrains.jet.lang.psi.JetProperty; - -import java.util.Set; - -/** -* @author svtk -*/ -public class VariableInitializers { - private final Set possibleLocalInitializers = Sets.newHashSet(); - private boolean isInitialized; - private boolean isDeclared; - - public VariableInitializers(boolean isInitialized) { - this(isInitialized, false); - } - - public VariableInitializers(boolean isInitialized, boolean isDeclared) { - this.isInitialized = isInitialized; - this.isDeclared = isDeclared; - } - - public VariableInitializers(JetElement element, @Nullable VariableInitializers previous) { - isInitialized = true; - isDeclared = element instanceof JetProperty || (previous != null && previous.isDeclared()); - possibleLocalInitializers.add(element); - } - - public VariableInitializers(Set edgesData) { - isInitialized = true; - isDeclared = true; - for (VariableInitializers edgeData : edgesData) { - if (!edgeData.isInitialized) { - isInitialized = false; - } - if (!edgeData.isDeclared) { - isDeclared = false; - } - possibleLocalInitializers.addAll(edgeData.possibleLocalInitializers); - } - } - - public Set getPossibleLocalInitializers() { - return possibleLocalInitializers; - } - - public boolean isInitialized() { - return isInitialized; - } - - public boolean isDeclared() { - return isDeclared; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof VariableInitializers)) return false; - - VariableInitializers that = (VariableInitializers) o; - - if (isDeclared != that.isDeclared) return false; - if (isInitialized != that.isInitialized) return false; - if (possibleLocalInitializers != null - ? !possibleLocalInitializers.equals(that.possibleLocalInitializers) - : that.possibleLocalInitializers != null) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = possibleLocalInitializers != null ? possibleLocalInitializers.hashCode() : 0; - result = 31 * result + (isInitialized ? 1 : 0); - result = 31 * result + (isDeclared ? 1 : 0); - return result; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java deleted file mode 100644 index 0d1b6bb7a9e..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/VariableUseStatus.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2012 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 org.jetbrains.jet.lang.cfg.data; - -import org.jetbrains.annotations.Nullable; - -/** -* @author svtk -*/ -public enum VariableUseStatus { - LAST_READ(3), - LAST_WRITTEN(2), - ONLY_WRITTEN_NEVER_READ(1), - UNUSED(0); - - private final int importance; - - VariableUseStatus(int importance) { - this.importance = importance; - } - - public VariableUseStatus merge(@Nullable VariableUseStatus variableUseStatus) { - if (variableUseStatus == null || importance > variableUseStatus.importance) return this; - return variableUseStatus; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java index f82ce6c46d6..cffada00275 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeUtil.java @@ -17,10 +17,14 @@ package org.jetbrains.jet.lang.cfg.pseudocode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -65,4 +69,18 @@ public class PseudocodeUtil { return new JetControlFlowProcessor(mockTrace).generatePseudocode(declaration); } + @Nullable + public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull Instruction instruction, boolean onlyReference, @NotNull BindingContext bindingContext) { + JetElement element = null; + if (instruction instanceof ReadValueInstruction) { + element = ((ReadValueInstruction) instruction).getElement(); + } + else if (instruction instanceof WriteValueInstruction) { + element = ((WriteValueInstruction) instruction).getlValue(); + } + else if (instruction instanceof VariableDeclarationInstruction) { + element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + } + return BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, element, onlyReference); + } } From a79ea0c86b642e7ebff2b63e461e119b96722eaa Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Sat, 26 May 2012 17:01:07 +0400 Subject: [PATCH 14/24] changes in 'PseudocodeTraverser' interface --- .../lang/cfg/JetFlowInformationProvider.java | 49 +++---- .../jet/lang/cfg/PseudocodeTraverser.java | 88 ++++++------ .../jet/lang/cfg/PseudocodeVariablesData.java | 130 ++++++++++-------- 3 files changed, 139 insertions(+), 128 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index a271bf70c6f..cc6166b160f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -24,7 +24,7 @@ import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.pseudocode.*; -import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges; +import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*; import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitializers; import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseStatus; import org.jetbrains.jet.lang.descriptors.*; @@ -189,14 +189,14 @@ public class JetFlowInformationProvider { Map>> initializers = pseudocodeData.getVariableInitializers(); final Set declaredVariables = pseudocodeData.getDeclaredVariables(pseudocode); - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, initializers, true, new PseudocodeTraverser.InstructionDataAnalyzeStrategy>() { + PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy>() { @Override public void execute(@NotNull Instruction instruction, @Nullable Map in, @Nullable Map out) { assert in != null && out != null; VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, - trace.getBindingContext()); + trace.getBindingContext()); if (variableDescriptor == null) return; if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return; VariableInitializers outInitializers = out.get(variableDescriptor); @@ -356,7 +356,9 @@ public class JetFlowInformationProvider { } PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor); boolean insideSelfAccessors = PsiTreeUtil.isAncestor(property, element, false); - if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor) && !insideSelfAccessors) { // not to generate error in accessors of abstract properties, there is one: declared accessor of abstract property + if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor) && + !insideSelfAccessors) { // not to generate error in accessors of abstract properties, there is one: declared accessor of abstract property + if (((PropertyDescriptor) variableDescriptor).getModality() == Modality.ABSTRACT) { trace.report(NO_BACKING_FIELD_ABSTRACT_PROPERTY.on(element)); } @@ -412,8 +414,9 @@ public class JetFlowInformationProvider { // "Unused variable" & "unused value" analyses public void markUnusedVariables() { - Map>> variableStatusData = pseudocodeData.getVariableStatusData(); - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, variableStatusData, false, new PseudocodeTraverser.InstructionDataAnalyzeStrategy>() { + Map>> variableStatusData = pseudocodeData.getVariableUseStatusData(); + InstructionDataAnalyzeStrategy> variableStatusAnalyzeStrategy = + new InstructionDataAnalyzeStrategy>() { @Override public void execute(@NotNull Instruction instruction, @Nullable Map in, @@ -422,7 +425,7 @@ public class JetFlowInformationProvider { assert in != null && out != null; Set declaredVariables = pseudocodeData.getDeclaredVariables(instruction.getOwner()); VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, - trace.getBindingContext()); + trace.getBindingContext()); if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) || !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return; VariableUseStatus variableUseStatus = in.get(variableDescriptor); @@ -438,8 +441,7 @@ public class JetFlowInformationProvider { } } else if (element instanceof JetPostfixExpression) { - IElementType operationToken = - ((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType(); + IElementType operationToken = ((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType(); if (operationToken == JetTokens.PLUSPLUS || operationToken == JetTokens.MINUSMINUS) { trace.report(Errors.UNUSED_CHANGED_VALUE.on(element, element)); } @@ -458,28 +460,19 @@ public class JetFlowInformationProvider { else if (element instanceof JetParameter) { PsiElement psiElement = element.getParent().getParent(); if (psiElement instanceof JetFunction) { - boolean isMain = (psiElement instanceof JetNamedFunction) && - JetMainDetector.isMain((JetNamedFunction) psiElement); - //todo - if (psiElement instanceof JetFunctionLiteral) { - //psiElement = psiElement.getParent(); - return; - } - DeclarationDescriptor descriptor = - trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); + boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement); + if (psiElement instanceof JetFunctionLiteral) return; + DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); assert descriptor instanceof FunctionDescriptor : psiElement.getText(); FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; - if (!isMain && - !functionDescriptor.getModality().isOverridable() && - functionDescriptor.getOverriddenDescriptors().isEmpty()) { + if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) { trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor)); } } } } - else if (variableUseStatus == VariableUseStatus.ONLY_WRITTEN_NEVER_READ && element instanceof JetProperty) { - trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE - .on((JetNamedDeclaration) element, variableDescriptor)); + else if (variableUseStatus == VariableUseStatus.ONLY_WRITTEN_NEVER_READ &&element instanceof JetProperty) { + trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor)); } else if (variableUseStatus == VariableUseStatus.LAST_WRITTEN && element instanceof JetProperty) { JetExpression initializer = ((JetProperty) element).getInitializer(); @@ -489,9 +482,9 @@ public class JetFlowInformationProvider { } } } - } - }); + }; + PseudocodeTraverser.traverse(pseudocode, false, true, variableStatusData, variableStatusAnalyzeStrategy); } //////////////////////////////////////////////////////////////////////////////// @@ -499,8 +492,8 @@ public class JetFlowInformationProvider { public void markUnusedLiteralsInBlock() { assert pseudocode != null; - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph( - pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { + PseudocodeTraverser.traverse( + pseudocode, true, new InstructionAnalyzeStrategy() { @Override public void execute(@NotNull Instruction instruction) { if (!(instruction instanceof ReadValueInstruction)) return; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index e8010b4d31a..b0a8e4884eb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -37,50 +37,46 @@ public class PseudocodeTraverser { return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } - public static Map> collectInformationFromInstructionGraph( - boolean lookInside, - boolean directOrder, - @NotNull Pseudocode pseudocode, - @NotNull D initialDataValue, - @NotNull D initialDataValueForEnterInstruction, + public static Map> collectInformation( + @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, + @NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy) { - Map> dataMap = Maps.newLinkedHashMap(); - initializeDataMap(lookInside, dataMap, pseudocode, initialDataValue); - dataMap.put(getStartInstruction(pseudocode, directOrder), - Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); + + Map> edgesMap = Maps.newLinkedHashMap(); + initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue); + edgesMap.put(getStartInstruction(pseudocode, directOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); boolean[] changed = new boolean[1]; changed[0] = true; while (changed[0]) { changed[0] = false; - traverseSubGraph(lookInside, pseudocode, dataMap, instructionDataMergeStrategy, Collections.emptyList(), directOrder, changed, false); + collectInformationFromSubgraph(pseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy, + Collections.emptyList(), changed, false); } - return dataMap; + return edgesMap; } - private static void initializeDataMap( - boolean lookInside, - @NotNull Map> dataMap, @NotNull Pseudocode pseudocode, + private static void initializeEdgesMap( + @NotNull Pseudocode pseudocode, boolean lookInside, + @NotNull Map> edgesMap, @NotNull D initialDataValue) { List instructions = pseudocode.getInstructions(); Edges initialEdge = Edges.create(initialDataValue, initialDataValue); for (Instruction instruction : instructions) { - dataMap.put(instruction, initialEdge); + edgesMap.put(instruction, initialEdge); if (lookInside && instruction instanceof LocalDeclarationInstruction) { - initializeDataMap(lookInside, dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue); + initializeEdgesMap(((LocalDeclarationInstruction) instruction).getBody(), lookInside, edgesMap, initialDataValue); } } } - private static void traverseSubGraph( - boolean lookInside, - @NotNull Pseudocode pseudocode, - @NotNull Map> dataMap, + private static void collectInformationFromSubgraph( + @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, + @NotNull Map> edgesMap, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, @NotNull Collection previousSubGraphInstructions, - boolean directOrder, - boolean[] changed, - boolean isLocal) { + boolean[] changed, boolean isLocal) { + List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); Instruction startInstruction = getStartInstruction(pseudocode, directOrder); @@ -101,22 +97,24 @@ public class PseudocodeTraverser { if (lookInside && instruction instanceof LocalDeclarationInstruction) { Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); - traverseSubGraph(lookInside, subroutinePseudocode, dataMap ,instructionDataMergeStrategy, previousInstructions, directOrder, changed, true); + collectInformationFromSubgraph(subroutinePseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy, + previousInstructions, + changed, true); Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); - Edges previousValue = dataMap.get(instruction); - Edges newValue = dataMap.get(lastInstruction); + Edges previousValue = edgesMap.get(instruction); + Edges newValue = edgesMap.get(lastInstruction); if (!previousValue.equals(newValue)) { changed[0] = true; - dataMap.put(instruction, newValue); + edgesMap.put(instruction, newValue); } continue; } - Edges previousDataValue = dataMap.get(instruction); + Edges previousDataValue = edgesMap.get(instruction); Collection incomingEdgesData = Sets.newHashSet(); for (Instruction previousInstruction : allPreviousInstructions) { - Edges previousData = dataMap.get(previousInstruction); + Edges previousData = edgesMap.get(previousInstruction); if (previousData != null) { incomingEdgesData.add(previousData.out); } @@ -124,36 +122,36 @@ public class PseudocodeTraverser { Edges mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData); if (!mergedData.equals(previousDataValue)) { changed[0] = true; - dataMap.put(instruction, mergedData); + edgesMap.put(instruction, mergedData); } } } - public static void traverseAndAnalyzeInstructionGraph( - @NotNull Pseudocode pseudocode, - boolean directOrder, - SimpleInstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { + public static void traverse( + @NotNull Pseudocode pseudocode, boolean directOrder, + InstructionAnalyzeStrategy instructionAnalyzeStrategy) { + List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); for (Instruction instruction : instructions) { if (instruction instanceof LocalDeclarationInstruction) { - traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionDataAnalyzeStrategy); + traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionAnalyzeStrategy); } - instructionDataAnalyzeStrategy.execute(instruction); + instructionAnalyzeStrategy.execute(instruction); } } - public static void traverseAndAnalyzeInstructionGraph( - boolean lookInside, - @NotNull Pseudocode pseudocode, - @NotNull Map> dataMap, - boolean directOrder, + public static void traverse( + @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, + @NotNull Map> edgesMap, @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { + List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); for (Instruction instruction : instructions) { if (lookInside && instruction instanceof LocalDeclarationInstruction) { - traverseAndAnalyzeInstructionGraph(lookInside, ((LocalDeclarationInstruction) instruction).getBody(), dataMap, directOrder, instructionDataAnalyzeStrategy); + traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, lookInside, edgesMap, + instructionDataAnalyzeStrategy); } - Edges edges = dataMap.get(instruction); + Edges edges = edgesMap.get(instruction); instructionDataAnalyzeStrategy.execute(instruction, edges != null ? edges.in : null, edges != null ? edges.out : null); } } @@ -166,7 +164,7 @@ public class PseudocodeTraverser { void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData); } - public interface SimpleInstructionDataAnalyzeStrategy { + public interface InstructionAnalyzeStrategy { void execute(@NotNull Instruction instruction); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index 9247f6d1189..c75e869cfe3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -20,7 +20,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges; +import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*; import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; @@ -57,11 +57,12 @@ public class PseudocodeVariablesData { return pseudocode; } + @NotNull public Set getUsedVariables(@NotNull Pseudocode pseudocode) { Set usedVariables = usedVariablesInEachDeclaration.get(pseudocode); if (usedVariables == null) { final Set result = Sets.newHashSet(); - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() { + PseudocodeTraverser.traverse(pseudocode, true, new InstructionAnalyzeStrategy() { @Override public void execute(@NotNull Instruction instruction) { VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, @@ -77,6 +78,7 @@ public class PseudocodeVariablesData { return usedVariables; } + @NotNull public Set getDeclaredVariables(@NotNull Pseudocode pseudocode) { Set declaredVariables = declaredVariablesInEachDeclaration.get(pseudocode); if (declaredVariables == null) { @@ -108,22 +110,24 @@ public class PseudocodeVariablesData { } @NotNull - private Map>> getVariableInitializers(Pseudocode pseudocode) { + private Map>> getVariableInitializers(@NotNull Pseudocode pseudocode) { Set usedVariables = getUsedVariables(pseudocode); Set declaredVariables = getDeclaredVariables(pseudocode); - final Map initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables); + Map initialMap = Collections.emptyMap(); + final Map initialMapForStartInstruction = prepareInitializersMapForStartInstruction( + usedVariables, declaredVariables); - Map>> variableInitializersMap = PseudocodeTraverser.collectInformationFromInstructionGraph(false, true, pseudocode, - Collections.emptyMap(), initialMapForStartInstruction, - new PseudocodeTraverser.InstructionDataMergeStrategy>() { + Map>> variableInitializersMap = PseudocodeTraverser.collectInformation( + pseudocode, /* directOrder = */ true, /* lookInside = */ false, + initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override public Edges> execute( - @NotNull Instruction instruction, - @NotNull Collection> incomingEdgesData) { + @NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { - Map enterInstructionData = mergeIncomingEdgesData(incomingEdgesData); - Map exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); + Map enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData); + Map exitInstructionData = + addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); return Edges.create(enterInstructionData, exitInstructionData); } }); @@ -144,7 +148,11 @@ public class PseudocodeVariablesData { return variableInitializersMap; } - private Map prepareInitialMapForStartInstruction(Collection usedVariables, Collection declaredVariables) { + @NotNull + private Map prepareInitializersMapForStartInstruction( + @NotNull Collection usedVariables, + @NotNull Collection declaredVariables) { + Map initialMapForStartInstruction = Maps.newHashMap(); VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true); VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false); @@ -160,7 +168,10 @@ public class PseudocodeVariablesData { return initialMapForStartInstruction; } - private Map mergeIncomingEdgesData(Collection> incomingEdgesData) { + @NotNull + private Map mergeIncomingEdgesDataForInitializers( + @NotNull Collection> incomingEdgesData) { + Set variablesInScope = Sets.newHashSet(); for (Map edgeData : incomingEdgesData) { variablesInScope.addAll(edgeData.keySet()); @@ -180,7 +191,10 @@ public class PseudocodeVariablesData { return enterInstructionData; } - private Map addVariableInitializerFromCurrentInstructionIfAny(Instruction instruction, Map enterInstructionData) { + @NotNull + private Map addVariableInitializerFromCurrentInstructionIfAny( + @NotNull Instruction instruction, @NotNull Map enterInstructionData) { + if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) { return enterInstructionData; } @@ -214,49 +228,55 @@ public class PseudocodeVariablesData { // variable use @NotNull - public Map>> getVariableStatusData() { + public Map>> getVariableUseStatusData() { if (variableStatusMap == null) { - Map sinkInstructionData = Maps.newHashMap(); - for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) { - sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); - } - variableStatusMap = PseudocodeTraverser.collectInformationFromInstructionGraph(true, false, pseudocode, - Collections.emptyMap(), sinkInstructionData, - new PseudocodeTraverser.InstructionDataMergeStrategy>() { - @Override - public Edges> execute(@NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { - Map enterResult = Maps.newHashMap(); - for (Map edgeData : incomingEdgesData) { - for (Map.Entry entry : edgeData.entrySet()) { - VariableDescriptor variableDescriptor = entry.getKey(); - VariableUseStatus variableUseStatus = entry.getValue(); - enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor))); - } - } - VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, bindingContext); - if (variableDescriptor == null || (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) { - return Edges.create(enterResult, enterResult); - } - Map exitResult = Maps.newHashMap(enterResult); - if (instruction instanceof ReadValueInstruction) { - exitResult.put(variableDescriptor, VariableUseStatus.LAST_READ); - } - else { - VariableUseStatus variableUseStatus = enterResult.get(variableDescriptor); - if (variableUseStatus == null) variableUseStatus = VariableUseStatus.UNUSED; - switch (variableUseStatus) { - case UNUSED: - case ONLY_WRITTEN_NEVER_READ: - exitResult.put(variableDescriptor, VariableUseStatus.ONLY_WRITTEN_NEVER_READ); - break; - case LAST_WRITTEN: - case LAST_READ: - exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN); - } - } - return Edges.create(enterResult, exitResult); + Map sinkInstructionData = Maps.newHashMap(); + for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) { + sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); } - }); + InstructionDataMergeStrategy> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy>() { + @Override + public Edges> execute(@NotNull Instruction instruction, + @NotNull Collection> incomingEdgesData) { + + Map enterResult = Maps.newHashMap(); + for (Map edgeData : incomingEdgesData) { + for (Map.Entry entry : edgeData.entrySet()) { + VariableDescriptor variableDescriptor = entry.getKey(); + VariableUseStatus variableUseStatus = entry.getValue(); + enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor))); + } + } + VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, + bindingContext); + if (variableDescriptor == null || + (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) { + return Edges.create(enterResult, enterResult); + } + Map exitResult = Maps.newHashMap(enterResult); + if (instruction instanceof ReadValueInstruction) { + exitResult.put(variableDescriptor, VariableUseStatus.LAST_READ); + } + else { + VariableUseStatus variableUseStatus = enterResult.get(variableDescriptor); + if (variableUseStatus == null) { + variableUseStatus = VariableUseStatus.UNUSED; + } + switch (variableUseStatus) { + case UNUSED: + case ONLY_WRITTEN_NEVER_READ: + exitResult.put(variableDescriptor, VariableUseStatus.ONLY_WRITTEN_NEVER_READ); + break; + case LAST_WRITTEN: + case LAST_READ: + exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN); + } + } + return Edges.create(enterResult, exitResult); + } + }; + variableStatusMap = PseudocodeTraverser.collectInformation(pseudocode, false, true, + Collections.emptyMap(), sinkInstructionData, collectVariableUseStatusStrategy); } return variableStatusMap; } From dfbd9922d9ec31ab244d90ba7f9f824dc17e5a17 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 28 May 2012 12:32:45 +0400 Subject: [PATCH 15/24] fixes after merge get rid of JetControlFlowDataTraceFactory --- .idea/inspectionProfiles/idea_default.xml | 3 ++ .idea/runConfigurations/Js_backend_tests.xml | 4 +- .../di/InjectorForTopDownAnalyzerForJvm.java | 42 ++++++++++++++----- .../resolve/java/AnalyzerFacadeForJVM.java | 35 +++++----------- .../jet/analyzer/AnalyzerFacade.java | 5 +-- .../di/InjectorForTopDownAnalyzerBasic.java | 36 +++++++++++----- .../project/AnalyzerFacadeWithCache.java | 5 +-- .../project/JSAnalyzerFacadeForIDEA.java | 5 +-- .../JetIntroduceVariableHandler.java | 1 - .../di/InjectorForTopDownAnalyzerForJs.java | 36 +++++++++++----- .../k2js/analyze/AnalyzerFacadeForJS.java | 7 +--- 11 files changed, 104 insertions(+), 75 deletions(-) diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml index 23bae163cd7..6c2f8ad45ac 100644 --- a/.idea/inspectionProfiles/idea_default.xml +++ b/.idea/inspectionProfiles/idea_default.xml @@ -410,6 +410,9 @@ diff --git a/.idea/runConfigurations/Js_backend_tests.xml b/.idea/runConfigurations/Js_backend_tests.xml index f743bf7dde6..95f27eae686 100644 --- a/.idea/runConfigurations/Js_backend_tests.xml +++ b/.idea/runConfigurations/Js_backend_tests.xml @@ -26,8 +26,6 @@ - - + \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 5f98e0cdbbe..fa918fa82e8 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -17,16 +17,42 @@ package org.jetbrains.jet.di; +import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext; +import org.jetbrains.jet.lang.resolve.BodyResolver; +import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer; +import org.jetbrains.jet.lang.resolve.DeclarationsChecker; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; +import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; -import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; +import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; +import org.jetbrains.jet.lang.resolve.java.JavaBridgeConfiguration; +import org.jetbrains.jet.lang.resolve.java.PsiClassFinderForJvm; +import org.jetbrains.jet.lang.resolve.DeclarationResolver; +import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; -import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; -import org.jetbrains.jet.lang.resolve.java.*; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; - +import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; +import org.jetbrains.jet.lang.resolve.ImportsResolver; +import org.jetbrains.jet.lang.resolve.DelegationResolver; +import org.jetbrains.jet.lang.resolve.NamespaceFactoryImpl; +import org.jetbrains.jet.lang.resolve.OverloadResolver; +import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver; +import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JavaTypeTransformer; +import com.intellij.openapi.project.Project; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; +import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; +import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ @@ -42,7 +68,6 @@ public class InjectorForTopDownAnalyzerForJvm { private final TopDownAnalysisParameters topDownAnalysisParameters; private final ObservableBindingTrace observableBindingTrace; private final ModuleDescriptor moduleDescriptor; - private final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory; private final CompilerDependencies compilerDependencies; private CompilerSpecialMode compilerSpecialMode; private JavaBridgeConfiguration javaBridgeConfiguration; @@ -69,7 +94,6 @@ public class InjectorForTopDownAnalyzerForJvm { @NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull ObservableBindingTrace observableBindingTrace, @NotNull ModuleDescriptor moduleDescriptor, - JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory, @NotNull CompilerDependencies compilerDependencies ) { this.topDownAnalyzer = new TopDownAnalyzer(); @@ -82,7 +106,6 @@ public class InjectorForTopDownAnalyzerForJvm { this.topDownAnalysisParameters = topDownAnalysisParameters; this.observableBindingTrace = observableBindingTrace; this.moduleDescriptor = moduleDescriptor; - this.jetControlFlowDataTraceFactory = jetControlFlowDataTraceFactory; this.compilerDependencies = compilerDependencies; this.compilerSpecialMode = compilerDependencies.getCompilerSpecialMode(); this.javaBridgeConfiguration = new JavaBridgeConfiguration(); @@ -126,7 +149,6 @@ public class InjectorForTopDownAnalyzerForJvm { this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); this.bodyResolver.setTrace(observableBindingTrace); - this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory); this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); this.controlFlowAnalyzer.setTrace(observableBindingTrace); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java index 75e2cf1db01..5b14ec0e973 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java @@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzerFacade; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.*; @@ -50,9 +49,8 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { @NotNull public AnalyzeExhaust analyzeFiles(@NotNull Project project, @NotNull Collection files, - @NotNull Predicate filesToAnalyzeCompletely, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { - return analyzeFilesWithJavaIntegration(project, files, filesToAnalyzeCompletely, flowDataTraceFactory, + @NotNull Predicate filesToAnalyzeCompletely) { + return analyzeFilesWithJavaIntegration(project, files, filesToAnalyzeCompletely, compilerDependenciesForProduction(CompilerSpecialMode.REGULAR), true); } @@ -60,22 +58,19 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { @Override public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project, @NotNull Predicate filesForBodiesResolve, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace headersTraceContext, @NotNull BodiesResolveContext bodiesResolveContext ) { return analyzeBodiesInFilesWithJavaIntegration( - project, filesForBodiesResolve, flowDataTraceFactory, - compilerDependenciesForProduction(CompilerSpecialMode.REGULAR), + project, filesForBodiesResolve, compilerDependenciesForProduction(CompilerSpecialMode.REGULAR), headersTraceContext, bodiesResolveContext); } public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors( - JetFile file, JetControlFlowDataTraceFactory flowDataTraceFactory, - @NotNull CompilerDependencies compilerDependencies) { + JetFile file, @NotNull CompilerDependencies compilerDependencies) { AnalyzingUtils.checkForSyntacticErrors(file); - AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, flowDataTraceFactory, compilerDependencies); + AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, compilerDependencies); AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext()); @@ -83,24 +78,20 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { } public static AnalyzeExhaust analyzeOneFileWithJavaIntegration( - JetFile file, JetControlFlowDataTraceFactory flowDataTraceFactory, - @NotNull CompilerDependencies compilerDependencies) { + JetFile file, @NotNull CompilerDependencies compilerDependencies) { return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file), - Predicates.alwaysTrue(), flowDataTraceFactory, compilerDependencies); + Predicates.alwaysTrue(), compilerDependencies); } public static AnalyzeExhaust analyzeFilesWithJavaIntegration( Project project, Collection files, Predicate filesToAnalyzeCompletely, - JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull CompilerDependencies compilerDependencies) { return analyzeFilesWithJavaIntegration( - project, files, filesToAnalyzeCompletely, - flowDataTraceFactory, compilerDependencies, false); + project, files, filesToAnalyzeCompletely, compilerDependencies, false); } public static AnalyzeExhaust analyzeFilesWithJavaIntegration( Project project, Collection files, Predicate filesToAnalyzeCompletely, - JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull CompilerDependencies compilerDependencies, boolean storeContextForBodiesResolve) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); @@ -112,8 +103,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm( project, topDownAnalysisParameters, - new ObservableBindingTrace(bindingTraceContext), owner, flowDataTraceFactory, - compilerDependencies); + new ObservableBindingTrace(bindingTraceContext), owner, compilerDependencies); try { injector.getTopDownAnalyzer().analyzeFiles(files); BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ? @@ -127,7 +117,6 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { public static AnalyzeExhaust analyzeBodiesInFilesWithJavaIntegration( Project project, Predicate filesToAnalyzeCompletely, - JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull CompilerDependencies compilerDependencies, @NotNull BindingTrace traceContext, @NotNull BodiesResolveContext bodiesResolveContext) { @@ -140,8 +129,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm( project, topDownAnalysisParameters, - new ObservableBindingTrace(traceContext), owner, flowDataTraceFactory, - compilerDependencies); + new ObservableBindingTrace(traceContext), owner, compilerDependencies); try { injector.getTopDownAnalyzer().doProcessForBodies(bodiesResolveContext); @@ -157,7 +145,6 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { Project project = files.iterator().next().getProject(); - return analyzeFilesWithJavaIntegration(project, files, Predicates.alwaysFalse(), - JetControlFlowDataTraceFactory.EMPTY, compilerDependencies); + return analyzeFilesWithJavaIntegration(project, files, Predicates.alwaysFalse(), compilerDependencies); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.java b/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.java index a80a65f787f..b5fd8f9768a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.java +++ b/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.java @@ -20,7 +20,6 @@ import com.google.common.base.Predicate; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BodiesResolveContext; @@ -35,13 +34,11 @@ public interface AnalyzerFacade { @NotNull AnalyzeExhaust analyzeFiles(@NotNull Project project, @NotNull Collection files, - @NotNull Predicate filesToAnalyzeCompletely, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory); + @NotNull Predicate filesToAnalyzeCompletely); @NotNull AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project, @NotNull Predicate filesForBodiesResolve, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace traceContext, @NotNull BodiesResolveContext bodiesResolveContext); } diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index 843ec10293a..6dda0b5f2e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -17,16 +17,36 @@ package org.jetbrains.jet.di; +import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext; +import org.jetbrains.jet.lang.resolve.BodyResolver; +import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer; +import org.jetbrains.jet.lang.resolve.DeclarationsChecker; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.ModuleConfiguration; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; +import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; -import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.ModuleConfiguration; +import org.jetbrains.jet.lang.resolve.DeclarationResolver; +import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; -import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; - +import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; +import org.jetbrains.jet.lang.resolve.ImportsResolver; +import org.jetbrains.jet.lang.resolve.DelegationResolver; +import org.jetbrains.jet.lang.resolve.NamespaceFactoryImpl; +import org.jetbrains.jet.lang.resolve.OverloadResolver; +import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver; +import com.intellij.openapi.project.Project; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; +import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.ModuleConfiguration; +import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ @@ -42,7 +62,6 @@ public class InjectorForTopDownAnalyzerBasic { private final TopDownAnalysisParameters topDownAnalysisParameters; private final ObservableBindingTrace observableBindingTrace; private final ModuleDescriptor moduleDescriptor; - private final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory; private final ModuleConfiguration moduleConfiguration; private DeclarationResolver declarationResolver; private AnnotationResolver annotationResolver; @@ -63,7 +82,6 @@ public class InjectorForTopDownAnalyzerBasic { @NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull ObservableBindingTrace observableBindingTrace, @NotNull ModuleDescriptor moduleDescriptor, - JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory, @NotNull ModuleConfiguration moduleConfiguration ) { this.topDownAnalyzer = new TopDownAnalyzer(); @@ -76,7 +94,6 @@ public class InjectorForTopDownAnalyzerBasic { this.topDownAnalysisParameters = topDownAnalysisParameters; this.observableBindingTrace = observableBindingTrace; this.moduleDescriptor = moduleDescriptor; - this.jetControlFlowDataTraceFactory = jetControlFlowDataTraceFactory; this.moduleConfiguration = moduleConfiguration; this.declarationResolver = new DeclarationResolver(); this.annotationResolver = new AnnotationResolver(); @@ -114,7 +131,6 @@ public class InjectorForTopDownAnalyzerBasic { this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); this.bodyResolver.setTrace(observableBindingTrace); - this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory); this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); this.controlFlowAnalyzer.setTrace(observableBindingTrace); diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java index dcd3b4bf4d1..4530622e00b 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java +++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java @@ -28,7 +28,6 @@ import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.JetFile; @@ -94,7 +93,6 @@ public final class AnalyzerFacadeWithCache { AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file).analyzeBodiesInFiles( file.getProject(), Predicates.equalTo(file), - JetControlFlowDataTraceFactory.EMPTY, new DelegatingBindingTrace(analyzeExhaustHeaders.getBindingContext()), context); @@ -137,8 +135,7 @@ public final class AnalyzerFacadeWithCache { AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache) .analyzeFiles(fileToCache.getProject(), headerFiles, - Predicates.alwaysFalse(), - JetControlFlowDataTraceFactory.EMPTY); + Predicates.alwaysFalse()); return new Result(exhaust, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); } diff --git a/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java b/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java index 78f8a8495df..72807df5609 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java +++ b/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java @@ -22,7 +22,6 @@ import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzerFacade; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BodiesResolveContext; @@ -44,8 +43,7 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade { @Override public AnalyzeExhaust analyzeFiles(@NotNull Project project, @NotNull Collection files, - @NotNull Predicate filesToAnalyzeCompletely, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { + @NotNull Predicate filesToAnalyzeCompletely) { return AnalyzerFacadeForJS.analyzeFiles(files, filesToAnalyzeCompletely, new IDEAConfig(project), true); } @@ -53,7 +51,6 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade { @Override public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project, @NotNull Predicate filesForBodiesResolve, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace traceContext, @NotNull BodiesResolveContext bodiesResolveContext) { return AnalyzerFacadeForJS.analyzeBodiesInFiles(filesForBodiesResolve, new IDEAConfig(project), traceContext, bodiesResolveContext); diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableHandler.java b/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableHandler.java index 73868932c9d..f3f9779a27e 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableHandler.java @@ -37,7 +37,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.di.InjectorForMacros; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.psi.*; diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 61bd7e28bc6..7986b6c610f 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -17,16 +17,36 @@ package org.jetbrains.jet.di; +import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext; +import org.jetbrains.jet.lang.resolve.BodyResolver; +import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer; +import org.jetbrains.jet.lang.resolve.DeclarationsChecker; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.ModuleConfiguration; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; +import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; -import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.ModuleConfiguration; +import org.jetbrains.jet.lang.resolve.DeclarationResolver; +import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; -import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; - +import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; +import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; +import org.jetbrains.jet.lang.resolve.ImportsResolver; +import org.jetbrains.jet.lang.resolve.DelegationResolver; +import org.jetbrains.jet.lang.resolve.NamespaceFactoryImpl; +import org.jetbrains.jet.lang.resolve.OverloadResolver; +import org.jetbrains.jet.lang.resolve.OverrideResolver; +import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver; +import com.intellij.openapi.project.Project; +import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; +import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.ModuleConfiguration; +import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ @@ -42,7 +62,6 @@ public class InjectorForTopDownAnalyzerForJs { private final TopDownAnalysisParameters topDownAnalysisParameters; private final ObservableBindingTrace observableBindingTrace; private final ModuleDescriptor moduleDescriptor; - private final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory; private final ModuleConfiguration moduleConfiguration; private DeclarationResolver declarationResolver; private AnnotationResolver annotationResolver; @@ -63,7 +82,6 @@ public class InjectorForTopDownAnalyzerForJs { @NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull ObservableBindingTrace observableBindingTrace, @NotNull ModuleDescriptor moduleDescriptor, - JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory, @NotNull ModuleConfiguration moduleConfiguration ) { this.topDownAnalyzer = new TopDownAnalyzer(); @@ -76,7 +94,6 @@ public class InjectorForTopDownAnalyzerForJs { this.topDownAnalysisParameters = topDownAnalysisParameters; this.observableBindingTrace = observableBindingTrace; this.moduleDescriptor = moduleDescriptor; - this.jetControlFlowDataTraceFactory = jetControlFlowDataTraceFactory; this.moduleConfiguration = moduleConfiguration; this.declarationResolver = new DeclarationResolver(); this.annotationResolver = new AnnotationResolver(); @@ -114,7 +131,6 @@ public class InjectorForTopDownAnalyzerForJs { this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); this.bodyResolver.setTrace(observableBindingTrace); - this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory); this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); this.controlFlowAnalyzer.setTrace(observableBindingTrace); diff --git a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java index 1c644c96496..f3927a837a3 100644 --- a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java +++ b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java @@ -28,7 +28,6 @@ import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJs; import org.jetbrains.jet.lang.DefaultModuleConfiguration; import org.jetbrains.jet.lang.ModuleConfiguration; -import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.psi.JetFile; @@ -91,8 +90,7 @@ public final class AnalyzerFacadeForJS { TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(completely, false, false); InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs( - project, topDownAnalysisParameters, new ObservableBindingTrace(bindingTraceContext), owner, - JetControlFlowDataTraceFactory.EMPTY, JsConfiguration.jsLibConfiguration(project)); + project, topDownAnalysisParameters, new ObservableBindingTrace(bindingTraceContext), owner, JsConfiguration.jsLibConfiguration(project)); try { injector.getTopDownAnalyzer().analyzeFiles(withJsLibAdded(files, config)); BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ? @@ -117,8 +115,7 @@ public final class AnalyzerFacadeForJS { TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(completely, false, false); InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs( - project, topDownAnalysisParameters, new ObservableBindingTrace(traceContext), owner, - JetControlFlowDataTraceFactory.EMPTY, JsConfiguration.jsLibConfiguration(project)); + project, topDownAnalysisParameters, new ObservableBindingTrace(traceContext), owner, JsConfiguration.jsLibConfiguration(project)); try { bodiesResolveContext.setTopDownAnalysisParameters(topDownAnalysisParameters); From 468052c3a537d11aed06fb0c6c3c6cb86e048c69 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 28 May 2012 13:00:47 +0400 Subject: [PATCH 16/24] renames --- .../lang/cfg/JetFlowInformationProvider.java | 21 +++++++++---------- .../jet/lang/cfg/PseudocodeTraverser.java | 14 ++++++------- .../jet/lang/cfg/PseudocodeVariablesData.java | 7 ++++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index cc6166b160f..3d2e70ecbbe 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -52,7 +52,7 @@ public class JetFlowInformationProvider { private final JetDeclaration subroutine; private final Pseudocode pseudocode; - private final PseudocodeVariablesData pseudocodeData; + private final PseudocodeVariablesData pseudocodeVariablesData; private BindingTrace trace; public JetFlowInformationProvider( @@ -62,7 +62,7 @@ public class JetFlowInformationProvider { subroutine = declaration; this.trace = trace; pseudocode = new JetControlFlowProcessor(trace).generatePseudocode(declaration); - pseudocodeData = new PseudocodeVariablesData(pseudocode, trace.getBindingContext()); + pseudocodeVariablesData = new PseudocodeVariablesData(pseudocode, trace.getBindingContext()); } private void collectReturnExpressions(@NotNull final Collection returnedExpressions) { @@ -187,16 +187,15 @@ public class JetFlowInformationProvider { final Collection varWithValReassignErrorGenerated = Sets.newHashSet(); final boolean processClassOrObject = subroutine instanceof JetClassOrObject; - Map>> initializers = pseudocodeData.getVariableInitializers(); - final Set declaredVariables = pseudocodeData.getDeclaredVariables(pseudocode); + Map>> initializers = pseudocodeVariablesData.getVariableInitializers(); + final Set declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode); PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy>() { @Override public void execute(@NotNull Instruction instruction, @Nullable Map in, @Nullable Map out) { assert in != null && out != null; - VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, - trace.getBindingContext()); + VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, trace.getBindingContext()); if (variableDescriptor == null) return; if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return; VariableInitializers outInitializers = out.get(variableDescriptor); @@ -224,7 +223,7 @@ public class JetFlowInformationProvider { } }); - Pseudocode pseudocode = pseudocodeData.getPseudocode(); + Pseudocode pseudocode = pseudocodeVariablesData.getPseudocode(); recordInitializedVariables(pseudocode, initializers); for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) { recordInitializedVariables(instruction.getBody(), initializers); @@ -399,8 +398,8 @@ public class JetFlowInformationProvider { private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map>> initializersMap) { Edges> initializers = initializersMap.get(pseudocode.getExitInstruction()); - Set usedVariables = pseudocodeData.getUsedVariables(pseudocode); - Set declaredVariables = pseudocodeData.getDeclaredVariables(pseudocode); + Set usedVariables = pseudocodeVariablesData.getUsedVariables(pseudocode); + Set declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode); for (VariableDescriptor variable : usedVariables) { if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) { VariableInitializers variableInitializers = initializers.in.get(variable); @@ -414,7 +413,7 @@ public class JetFlowInformationProvider { // "Unused variable" & "unused value" analyses public void markUnusedVariables() { - Map>> variableStatusData = pseudocodeData.getVariableUseStatusData(); + Map>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData(); InstructionDataAnalyzeStrategy> variableStatusAnalyzeStrategy = new InstructionDataAnalyzeStrategy>() { @Override @@ -423,7 +422,7 @@ public class JetFlowInformationProvider { @Nullable Map out) { assert in != null && out != null; - Set declaredVariables = pseudocodeData.getDeclaredVariables(instruction.getOwner()); + Set declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.getOwner()); VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, trace.getBindingContext()); if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) || diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index b0a8e4884eb..77781e4e20b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -37,7 +37,7 @@ public class PseudocodeTraverser { return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } - public static Map> collectInformation( + public static Map> collectData( @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, @NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy) { @@ -50,8 +50,8 @@ public class PseudocodeTraverser { changed[0] = true; while (changed[0]) { changed[0] = false; - collectInformationFromSubgraph(pseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy, - Collections.emptyList(), changed, false); + collectDataFromSubgraph(pseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy, + Collections.emptyList(), changed, false); } return edgesMap; } @@ -70,7 +70,7 @@ public class PseudocodeTraverser { } } - private static void collectInformationFromSubgraph( + private static void collectDataFromSubgraph( @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, @NotNull Map> edgesMap, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, @@ -97,9 +97,9 @@ public class PseudocodeTraverser { if (lookInside && instruction instanceof LocalDeclarationInstruction) { Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); - collectInformationFromSubgraph(subroutinePseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy, - previousInstructions, - changed, true); + collectDataFromSubgraph(subroutinePseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy, + previousInstructions, + changed, true); Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); Edges previousValue = edgesMap.get(instruction); Edges newValue = edgesMap.get(lastInstruction); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index c75e869cfe3..25704d635e7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -118,7 +118,7 @@ public class PseudocodeVariablesData { final Map initialMapForStartInstruction = prepareInitializersMapForStartInstruction( usedVariables, declaredVariables); - Map>> variableInitializersMap = PseudocodeTraverser.collectInformation( + Map>> variableInitializersMap = PseudocodeTraverser.collectData( pseudocode, /* directOrder = */ true, /* lookInside = */ false, initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override @@ -275,8 +275,9 @@ public class PseudocodeVariablesData { return Edges.create(enterResult, exitResult); } }; - variableStatusMap = PseudocodeTraverser.collectInformation(pseudocode, false, true, - Collections.emptyMap(), sinkInstructionData, collectVariableUseStatusStrategy); + variableStatusMap = PseudocodeTraverser.collectData(pseudocode, false, true, + Collections.emptyMap(), + sinkInstructionData, collectVariableUseStatusStrategy); } return variableStatusMap; } From de67cae5717961c8b23e2df096cba15efb1fc618 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 28 May 2012 13:48:49 +0400 Subject: [PATCH 17/24] no need in possible local initializers for each variable for each instruction rename --- .../lang/cfg/JetFlowInformationProvider.java | 79 ++++---- .../jet/lang/cfg/PseudocodeTraverser.java | 10 - .../jet/lang/cfg/PseudocodeVariablesData.java | 182 ++++++++---------- 3 files changed, 120 insertions(+), 151 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 3d2e70ecbbe..d3c15f80923 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -25,8 +25,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*; -import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitializers; -import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseStatus; +import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitState; +import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; @@ -41,6 +41,7 @@ import org.jetbrains.jet.plugin.JetMainDetector; import java.util.*; +import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; @@ -187,38 +188,38 @@ public class JetFlowInformationProvider { final Collection varWithValReassignErrorGenerated = Sets.newHashSet(); final boolean processClassOrObject = subroutine instanceof JetClassOrObject; - Map>> initializers = pseudocodeVariablesData.getVariableInitializers(); + Map>> initializers = pseudocodeVariablesData.getVariableInitializers(); final Set declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode); - PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy>() { + PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy>() { @Override public void execute(@NotNull Instruction instruction, - @Nullable Map in, - @Nullable Map out) { + @Nullable Map in, + @Nullable Map out) { assert in != null && out != null; VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, trace.getBindingContext()); if (variableDescriptor == null) return; if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return; - VariableInitializers outInitializers = out.get(variableDescriptor); + VariableInitState outInitState = out.get(variableDescriptor); if (instruction instanceof ReadValueInstruction) { JetElement element = ((ReadValueInstruction) instruction).getElement(); boolean error = checkBackingField(variableDescriptor, element); if (!error && declaredVariables.contains(variableDescriptor)) { - checkIsInitialized(variableDescriptor, element, outInitializers, varWithUninitializedErrorGenerated); + checkIsInitialized(variableDescriptor, element, outInitState, varWithUninitializedErrorGenerated); } return; } JetElement element = ((WriteValueInstruction) instruction).getlValue(); boolean error = checkBackingField(variableDescriptor, element); if (!(element instanceof JetExpression)) return; - VariableInitializers inInitializers = in.get(variableDescriptor); + PseudocodeVariablesData.VariableInitState inInitState = in.get(variableDescriptor); if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration - error = checkValReassignment(variableDescriptor, (JetExpression) element, inInitializers, varWithValReassignErrorGenerated); + error = checkValReassignment(variableDescriptor, (JetExpression) element, inInitState, varWithValReassignErrorGenerated); } if (!error && processClassOrObject) { - error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, inInitializers, outInitializers); + error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, inInitState, outInitState); } if (!error && processClassOrObject) { - checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, inInitializers, outInitializers); + checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, inInitState, outInitState); } } }); @@ -232,11 +233,11 @@ public class JetFlowInformationProvider { private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, @NotNull JetElement element, - @NotNull VariableInitializers variableInitializers, + @NotNull PseudocodeVariablesData.VariableInitState variableInitState, @NotNull Collection varWithUninitializedErrorGenerated) { if (!(element instanceof JetSimpleNameExpression)) return; - boolean isInitialized = variableInitializers.isInitialized(); + boolean isInitialized = variableInitState.isInitialized; if (variableDescriptor instanceof PropertyDescriptor) { if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) { isInitialized = true; @@ -256,15 +257,11 @@ public class JetFlowInformationProvider { private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, - @NotNull VariableInitializers enterInitializers, + @NotNull VariableInitState enterInitState, @NotNull Collection varWithValReassignErrorGenerated) { - boolean isInitializedNotHere = enterInitializers.isInitialized(); - Set possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers(); - if (possibleLocalInitializers.size() == 1) { - JetElement initializer = possibleLocalInitializers.iterator().next(); - if (initializer instanceof JetProperty && initializer == expression.getParent()) { - isInitializedNotHere = false; - } + boolean isInitializedNotHere = enterInitState.isInitialized; + if (expression.getParent() instanceof JetProperty && ((JetProperty)expression).getInitializer() != null) { + isInitializedNotHere = false; } boolean hasBackingField = true; if (variableDescriptor instanceof PropertyDescriptor) { @@ -307,16 +304,16 @@ public class JetFlowInformationProvider { return false; } - private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) { - if (!enterInitializers.isDeclared() && !exitInitializers.isDeclared() && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) { + private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) { + if (!enterInitState.isDeclared && !exitInitState.isDeclared && !enterInitState.isInitialized && exitInitState.isInitialized) { trace.report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, variableDescriptor)); return true; } return false; } - private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) { - if (variableDescriptor instanceof PropertyDescriptor && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) { + private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) { + if (variableDescriptor instanceof PropertyDescriptor && !enterInitState.isInitialized && exitInitState.isInitialized) { if (!variableDescriptor.isVar()) return false; if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return false; PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor); @@ -396,15 +393,15 @@ public class JetFlowInformationProvider { return false; } - private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map>> initializersMap) { - Edges> initializers = initializersMap.get(pseudocode.getExitInstruction()); + private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map>> initializersMap) { + Edges> initializers = initializersMap.get(pseudocode.getExitInstruction()); Set usedVariables = pseudocodeVariablesData.getUsedVariables(pseudocode); Set declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode); for (VariableDescriptor variable : usedVariables) { if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) { - VariableInitializers variableInitializers = initializers.in.get(variable); - if (variableInitializers == null) return; - trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitializers.isInitialized()); + PseudocodeVariablesData.VariableInitState variableInitState = initializers.in.get(variable); + if (variableInitState == null) return; + trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitState.isInitialized); } } } @@ -413,13 +410,13 @@ public class JetFlowInformationProvider { // "Unused variable" & "unused value" analyses public void markUnusedVariables() { - Map>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData(); - InstructionDataAnalyzeStrategy> variableStatusAnalyzeStrategy = - new InstructionDataAnalyzeStrategy>() { + Map>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData(); + InstructionDataAnalyzeStrategy> variableStatusAnalyzeStrategy = + new InstructionDataAnalyzeStrategy>() { @Override public void execute(@NotNull Instruction instruction, - @Nullable Map in, - @Nullable Map out) { + @Nullable Map in, + @Nullable Map out) { assert in != null && out != null; Set declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.getOwner()); @@ -427,11 +424,11 @@ public class JetFlowInformationProvider { trace.getBindingContext()); if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) || !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return; - VariableUseStatus variableUseStatus = in.get(variableDescriptor); + PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor); if (instruction instanceof WriteValueInstruction) { if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return; JetElement element = ((WriteValueInstruction) instruction).getElement(); - if (variableUseStatus != VariableUseStatus.LAST_READ) { + if (variableUseState != LAST_READ) { if (element instanceof JetBinaryExpression && ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) { JetExpression right = ((JetBinaryExpression) element).getRight(); @@ -452,7 +449,7 @@ public class JetFlowInformationProvider { if (element instanceof JetNamedDeclaration) { PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier(); if (nameIdentifier == null) return; - if (variableUseStatus == null || variableUseStatus == VariableUseStatus.UNUSED) { + if (variableUseState == null || variableUseState == UNUSED) { if (element instanceof JetProperty) { trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor)); } @@ -470,10 +467,10 @@ public class JetFlowInformationProvider { } } } - else if (variableUseStatus == VariableUseStatus.ONLY_WRITTEN_NEVER_READ &&element instanceof JetProperty) { + else if (variableUseState == ONLY_WRITTEN_NEVER_READ &&element instanceof JetProperty) { trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor)); } - else if (variableUseStatus == VariableUseStatus.LAST_WRITTEN && element instanceof JetProperty) { + else if (variableUseState == LAST_WRITTEN && element instanceof JetProperty) { JetExpression initializer = ((JetProperty) element).getInitializer(); if (initializer != null) { trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index 77781e4e20b..2c31612629b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -181,16 +181,6 @@ public class PseudocodeTraverser { return new Edges(in, out); } - @NotNull - public T getIn() { - return in; - } - - @NotNull - public T getOut() { - return out; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index 25704d635e7..23386867124 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -44,8 +44,8 @@ public class PseudocodeVariablesData { private final Map> declaredVariablesInEachDeclaration = Maps.newHashMap(); private final Map> usedVariablesInEachDeclaration = Maps.newHashMap(); - private Map>> variableInitializersMap; - private Map>> variableStatusMap; + private Map>> variableInitializersMap; + private Map>> variableStatusMap; public PseudocodeVariablesData(@NotNull Pseudocode pseudocode, @NotNull BindingContext bindingContext) { this.pseudocode = pseudocode; @@ -102,7 +102,7 @@ public class PseudocodeVariablesData { // variable initializers @NotNull - public Map>> getVariableInitializers() { + public Map>> getVariableInitializers() { if (variableInitializersMap == null) { variableInitializersMap = getVariableInitializers(pseudocode); } @@ -110,23 +110,23 @@ public class PseudocodeVariablesData { } @NotNull - private Map>> getVariableInitializers(@NotNull Pseudocode pseudocode) { + private Map>> getVariableInitializers(@NotNull Pseudocode pseudocode) { Set usedVariables = getUsedVariables(pseudocode); Set declaredVariables = getDeclaredVariables(pseudocode); - Map initialMap = Collections.emptyMap(); - final Map initialMapForStartInstruction = prepareInitializersMapForStartInstruction( + Map initialMap = Collections.emptyMap(); + final Map initialMapForStartInstruction = prepareInitializersMapForStartInstruction( usedVariables, declaredVariables); - Map>> variableInitializersMap = PseudocodeTraverser.collectData( + Map>> variableInitializersMap = PseudocodeTraverser.collectData( pseudocode, /* directOrder = */ true, /* lookInside = */ false, - initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy>() { + initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override - public Edges> execute( - @NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { + public Edges> execute( + @NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { - Map enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData); - Map exitInstructionData = + Map enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData); + Map exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); return Edges.create(enterInstructionData, exitInstructionData); } @@ -135,7 +135,7 @@ public class PseudocodeVariablesData { for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { Pseudocode localPseudocode = localDeclarationInstruction.getBody(); - Map>> initializersForLocalDeclaration = getVariableInitializers(localPseudocode); + Map>> initializersForLocalDeclaration = getVariableInitializers(localPseudocode); for (Instruction instruction : initializersForLocalDeclaration.keySet()) { //todo @@ -149,51 +149,51 @@ public class PseudocodeVariablesData { } @NotNull - private Map prepareInitializersMapForStartInstruction( + private Map prepareInitializersMapForStartInstruction( @NotNull Collection usedVariables, @NotNull Collection declaredVariables) { - Map initialMapForStartInstruction = Maps.newHashMap(); - VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true); - VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false); + Map initialMapForStartInstruction = Maps.newHashMap(); + VariableInitState initializedForExternalVariable = new VariableInitState(true); + VariableInitState notInitializedForDeclaredVariable = new VariableInitState(false); for (VariableDescriptor variable : usedVariables) { if (declaredVariables.contains(variable)) { - initialMapForStartInstruction.put(variable, isNotInitializedForDeclaredVariable); + initialMapForStartInstruction.put(variable, notInitializedForDeclaredVariable); } else { - initialMapForStartInstruction.put(variable, isInitializedForExternalVariable); + initialMapForStartInstruction.put(variable, initializedForExternalVariable); } } return initialMapForStartInstruction; } @NotNull - private Map mergeIncomingEdgesDataForInitializers( - @NotNull Collection> incomingEdgesData) { + private Map mergeIncomingEdgesDataForInitializers( + @NotNull Collection> incomingEdgesData) { Set variablesInScope = Sets.newHashSet(); - for (Map edgeData : incomingEdgesData) { + for (Map edgeData : incomingEdgesData) { variablesInScope.addAll(edgeData.keySet()); } - Map enterInstructionData = Maps.newHashMap(); + Map enterInstructionData = Maps.newHashMap(); for (VariableDescriptor variable : variablesInScope) { - Set edgesDataForVariable = Sets.newHashSet(); - for (Map edgeData : incomingEdgesData) { - VariableInitializers initializers = edgeData.get(variable); - if (initializers != null) { - edgesDataForVariable.add(initializers); + Set edgesDataForVariable = Sets.newHashSet(); + for (Map edgeData : incomingEdgesData) { + VariableInitState initState = edgeData.get(variable); + if (initState != null) { + edgesDataForVariable.add(initState); } } - enterInstructionData.put(variable, new VariableInitializers(edgesDataForVariable)); + enterInstructionData.put(variable, new VariableInitState(edgesDataForVariable)); } return enterInstructionData; } @NotNull - private Map addVariableInitializerFromCurrentInstructionIfAny( - @NotNull Instruction instruction, @NotNull Map enterInstructionData) { + private Map addVariableInitializerFromCurrentInstructionIfAny( + @NotNull Instruction instruction, @NotNull Map enterInstructionData) { if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) { return enterInstructionData; @@ -202,21 +202,22 @@ public class PseudocodeVariablesData { if (variable == null) { return enterInstructionData; } - Map exitInstructionData = Maps.newHashMap(enterInstructionData); + Map exitInstructionData = Maps.newHashMap(enterInstructionData); if (instruction instanceof WriteValueInstruction) { - VariableInitializers enterInitializers = enterInstructionData.get(variable); - VariableInitializers initializationAtThisElement = new VariableInitializers(((WriteValueInstruction) instruction).getElement(), enterInitializers); + VariableInitState enterInitState = enterInstructionData.get(variable); + VariableInitState initializationAtThisElement = + new VariableInitState(((WriteValueInstruction) instruction).getElement() instanceof JetProperty, enterInitState); exitInstructionData.put(variable, initializationAtThisElement); } - else { - VariableInitializers enterInitializers = enterInstructionData.get(variable); - if (enterInitializers == null || !enterInitializers.isInitialized() || !enterInitializers.isDeclared()) { + else { // instruction instanceof VariableDeclarationInstruction + VariableInitState enterInitState = enterInstructionData.get(variable); + if (enterInitState == null || !enterInitState.isInitialized || !enterInitState.isDeclared) { JetElement element = ((VariableDeclarationInstruction) instruction).getElement(); if (element instanceof JetProperty) { JetProperty property = (JetProperty) element; if (property.getInitializer() == null) { - boolean isInitialized = enterInitializers != null && enterInitializers.isInitialized(); - VariableInitializers variableDeclarationInfo = new VariableInitializers(isInitialized, true); + boolean isInitialized = enterInitState != null && enterInitState.isInitialized; + VariableInitState variableDeclarationInfo = new VariableInitState(isInitialized, true); exitInstructionData.put(variable, variableDeclarationInfo); } } @@ -228,23 +229,23 @@ public class PseudocodeVariablesData { // variable use @NotNull - public Map>> getVariableUseStatusData() { + public Map>> getVariableUseStatusData() { if (variableStatusMap == null) { - Map sinkInstructionData = Maps.newHashMap(); + Map sinkInstructionData = Maps.newHashMap(); for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) { - sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); + sinkInstructionData.put(usedVariable, VariableUseState.UNUSED); } - InstructionDataMergeStrategy> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy>() { + InstructionDataMergeStrategy> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy>() { @Override - public Edges> execute(@NotNull Instruction instruction, - @NotNull Collection> incomingEdgesData) { + public Edges> execute(@NotNull Instruction instruction, + @NotNull Collection> incomingEdgesData) { - Map enterResult = Maps.newHashMap(); - for (Map edgeData : incomingEdgesData) { - for (Map.Entry entry : edgeData.entrySet()) { + Map enterResult = Maps.newHashMap(); + for (Map edgeData : incomingEdgesData) { + for (Map.Entry entry : edgeData.entrySet()) { VariableDescriptor variableDescriptor = entry.getKey(); - VariableUseStatus variableUseStatus = entry.getValue(); - enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor))); + VariableUseState variableUseState = entry.getValue(); + enterResult.put(variableDescriptor, variableUseState.merge(enterResult.get(variableDescriptor))); } } VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, @@ -253,109 +254,90 @@ public class PseudocodeVariablesData { (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) { return Edges.create(enterResult, enterResult); } - Map exitResult = Maps.newHashMap(enterResult); + Map exitResult = Maps.newHashMap(enterResult); if (instruction instanceof ReadValueInstruction) { - exitResult.put(variableDescriptor, VariableUseStatus.LAST_READ); + exitResult.put(variableDescriptor, VariableUseState.LAST_READ); } - else { - VariableUseStatus variableUseStatus = enterResult.get(variableDescriptor); - if (variableUseStatus == null) { - variableUseStatus = VariableUseStatus.UNUSED; + else { //instruction instanceof WriteValueInstruction + VariableUseState variableUseState = enterResult.get(variableDescriptor); + if (variableUseState == null) { + variableUseState = VariableUseState.UNUSED; } - switch (variableUseStatus) { + switch (variableUseState) { case UNUSED: case ONLY_WRITTEN_NEVER_READ: - exitResult.put(variableDescriptor, VariableUseStatus.ONLY_WRITTEN_NEVER_READ); + exitResult.put(variableDescriptor, VariableUseState.ONLY_WRITTEN_NEVER_READ); break; case LAST_WRITTEN: case LAST_READ: - exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN); + exitResult.put(variableDescriptor, VariableUseState.LAST_WRITTEN); } } return Edges.create(enterResult, exitResult); } }; variableStatusMap = PseudocodeTraverser.collectData(pseudocode, false, true, - Collections.emptyMap(), + Collections.emptyMap(), sinkInstructionData, collectVariableUseStatusStrategy); } return variableStatusMap; } - public static class VariableInitializers { - private final Set possibleLocalInitializers = Sets.newHashSet(); - private boolean isInitialized; - private boolean isDeclared; + public static class VariableInitState { + public final boolean isInitialized; + public final boolean isDeclared; - public VariableInitializers(boolean isInitialized) { + public VariableInitState(boolean isInitialized) { this(isInitialized, false); } - public VariableInitializers(boolean isInitialized, boolean isDeclared) { + public VariableInitState(boolean isInitialized, boolean isDeclared) { this.isInitialized = isInitialized; this.isDeclared = isDeclared; } - public VariableInitializers(JetElement element, @Nullable VariableInitializers previous) { + public VariableInitState(boolean isDeclaredHere, @Nullable VariableInitState mergedEdgesData) { isInitialized = true; - isDeclared = element instanceof JetProperty || (previous != null && previous.isDeclared()); - possibleLocalInitializers.add(element); + isDeclared = isDeclaredHere || (mergedEdgesData != null && mergedEdgesData.isDeclared); } - public VariableInitializers(Set edgesData) { - isInitialized = true; - isDeclared = true; - for (VariableInitializers edgeData : edgesData) { + public VariableInitState(@NotNull Set edgesData) { + boolean isInitialized = true; + boolean isDeclared = true; + for (VariableInitState edgeData : edgesData) { if (!edgeData.isInitialized) { isInitialized = false; } if (!edgeData.isDeclared) { isDeclared = false; } - possibleLocalInitializers.addAll(edgeData.possibleLocalInitializers); } - } - - public Set getPossibleLocalInitializers() { - return possibleLocalInitializers; - } - - public boolean isInitialized() { - return isInitialized; - } - - public boolean isDeclared() { - return isDeclared; + this.isInitialized = isInitialized; + this.isDeclared = isDeclared; } @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof VariableInitializers)) return false; + if (!(o instanceof VariableInitState)) return false; - VariableInitializers that = (VariableInitializers) o; + VariableInitState that = (VariableInitState) o; if (isDeclared != that.isDeclared) return false; if (isInitialized != that.isInitialized) return false; - if (possibleLocalInitializers != null - ? !possibleLocalInitializers.equals(that.possibleLocalInitializers) - : that.possibleLocalInitializers != null) { - return false; - } return true; } @Override public int hashCode() { - int result = possibleLocalInitializers != null ? possibleLocalInitializers.hashCode() : 0; - result = 31 * result + (isInitialized ? 1 : 0); + int result = (isInitialized ? 1 : 0); result = 31 * result + (isDeclared ? 1 : 0); return result; } } - public static enum VariableUseStatus { + public static enum VariableUseState { LAST_READ(3), LAST_WRITTEN(2), ONLY_WRITTEN_NEVER_READ(1), @@ -363,13 +345,13 @@ public class PseudocodeVariablesData { private final int importance; - VariableUseStatus(int importance) { + VariableUseState(int importance) { this.importance = importance; } - public VariableUseStatus merge(@Nullable VariableUseStatus variableUseStatus) { - if (variableUseStatus == null || importance > variableUseStatus.importance) return this; - return variableUseStatus; + public VariableUseState merge(@Nullable VariableUseState variableUseState) { + if (variableUseState == null || importance > variableUseState.importance) return this; + return variableUseState; } } } From b4f765bd767d6f7014c2f190b64eeb30c7876248 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 28 May 2012 14:57:22 +0400 Subject: [PATCH 18/24] no different objects for VariableInitState --- .../lang/cfg/JetFlowInformationProvider.java | 4 +- .../jet/lang/cfg/PseudocodeVariablesData.java | 85 +++++++++---------- 2 files changed, 40 insertions(+), 49 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index d3c15f80923..be6a8f0028b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -449,7 +449,7 @@ public class JetFlowInformationProvider { if (element instanceof JetNamedDeclaration) { PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier(); if (nameIdentifier == null) return; - if (variableUseState == null || variableUseState == UNUSED) { + if (!VariableUseState.isUsed(variableUseState)) { if (element instanceof JetProperty) { trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor)); } @@ -467,7 +467,7 @@ public class JetFlowInformationProvider { } } } - else if (variableUseState == ONLY_WRITTEN_NEVER_READ &&element instanceof JetProperty) { + else if (variableUseState == ONLY_WRITTEN_NEVER_READ && element instanceof JetProperty) { trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor)); } else if (variableUseState == LAST_WRITTEN && element instanceof JetProperty) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index 23386867124..92f84ca62cd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -127,7 +127,7 @@ public class PseudocodeVariablesData { Map enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData); Map exitInstructionData = - addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); + addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData); return Edges.create(enterInstructionData, exitInstructionData); } }); @@ -154,8 +154,8 @@ public class PseudocodeVariablesData { @NotNull Collection declaredVariables) { Map initialMapForStartInstruction = Maps.newHashMap(); - VariableInitState initializedForExternalVariable = new VariableInitState(true); - VariableInitState notInitializedForDeclaredVariable = new VariableInitState(false); + VariableInitState initializedForExternalVariable = VariableInitState.create(true); + VariableInitState notInitializedForDeclaredVariable = VariableInitState.create(false); for (VariableDescriptor variable : usedVariables) { if (declaredVariables.contains(variable)) { @@ -186,13 +186,13 @@ public class PseudocodeVariablesData { edgesDataForVariable.add(initState); } } - enterInstructionData.put(variable, new VariableInitState(edgesDataForVariable)); + enterInstructionData.put(variable, VariableInitState.create(edgesDataForVariable)); } return enterInstructionData; } @NotNull - private Map addVariableInitializerFromCurrentInstructionIfAny( + private Map addVariableInitStateFromCurrentInstructionIfAny( @NotNull Instruction instruction, @NotNull Map enterInstructionData) { if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) { @@ -206,21 +206,15 @@ public class PseudocodeVariablesData { if (instruction instanceof WriteValueInstruction) { VariableInitState enterInitState = enterInstructionData.get(variable); VariableInitState initializationAtThisElement = - new VariableInitState(((WriteValueInstruction) instruction).getElement() instanceof JetProperty, enterInitState); + VariableInitState.create(((WriteValueInstruction) instruction).getElement() instanceof JetProperty, enterInitState); exitInstructionData.put(variable, initializationAtThisElement); } else { // instruction instanceof VariableDeclarationInstruction VariableInitState enterInitState = enterInstructionData.get(variable); if (enterInitState == null || !enterInitState.isInitialized || !enterInitState.isDeclared) { - JetElement element = ((VariableDeclarationInstruction) instruction).getElement(); - if (element instanceof JetProperty) { - JetProperty property = (JetProperty) element; - if (property.getInitializer() == null) { - boolean isInitialized = enterInitState != null && enterInitState.isInitialized; - VariableInitState variableDeclarationInfo = new VariableInitState(isInitialized, true); - exitInstructionData.put(variable, variableDeclarationInfo); - } - } + boolean isInitialized = enterInitState != null && enterInitState.isInitialized; + VariableInitState variableDeclarationInfo = VariableInitState.create(isInitialized, true); + exitInstructionData.put(variable, variableDeclarationInfo); } } return exitInstructionData; @@ -287,21 +281,35 @@ public class PseudocodeVariablesData { public final boolean isInitialized; public final boolean isDeclared; - public VariableInitState(boolean isInitialized) { - this(isInitialized, false); - } - - public VariableInitState(boolean isInitialized, boolean isDeclared) { + private VariableInitState(boolean isInitialized, boolean isDeclared) { this.isInitialized = isInitialized; this.isDeclared = isDeclared; } - public VariableInitState(boolean isDeclaredHere, @Nullable VariableInitState mergedEdgesData) { - isInitialized = true; - isDeclared = isDeclaredHere || (mergedEdgesData != null && mergedEdgesData.isDeclared); + private static final VariableInitState VS_TT = new VariableInitState(true, true); + private static final VariableInitState VS_TF = new VariableInitState(true, false); + private static final VariableInitState VS_FT = new VariableInitState(false, true); + private static final VariableInitState VS_FF = new VariableInitState(false, false); + + + private static VariableInitState create(boolean isInitialized, boolean isDeclared) { + if (isInitialized) { + if (isDeclared) return VS_TT; + return VS_TF; + } + if (isDeclared) return VS_FT; + return VS_FF; } - public VariableInitState(@NotNull Set edgesData) { + private static VariableInitState create(boolean isInitialized) { + return create(isInitialized, false); + } + + private static VariableInitState create(boolean isDeclaredHere, @Nullable VariableInitState mergedEdgesData) { + return create(true, isDeclaredHere || (mergedEdgesData != null && mergedEdgesData.isDeclared)); + } + + private static VariableInitState create(@NotNull Set edgesData) { boolean isInitialized = true; boolean isDeclared = true; for (VariableInitState edgeData : edgesData) { @@ -312,28 +320,7 @@ public class PseudocodeVariablesData { isDeclared = false; } } - this.isInitialized = isInitialized; - this.isDeclared = isDeclared; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof VariableInitState)) return false; - - VariableInitState that = (VariableInitState) o; - - if (isDeclared != that.isDeclared) return false; - if (isInitialized != that.isInitialized) return false; - - return true; - } - - @Override - public int hashCode() { - int result = (isInitialized ? 1 : 0); - result = 31 * result + (isDeclared ? 1 : 0); - return result; + return create(isInitialized, isDeclared); } } @@ -349,9 +336,13 @@ public class PseudocodeVariablesData { this.importance = importance; } - public VariableUseState merge(@Nullable VariableUseState variableUseState) { + private VariableUseState merge(@Nullable VariableUseState variableUseState) { if (variableUseState == null || importance > variableUseState.importance) return this; return variableUseState; } + + public static boolean isUsed(@Nullable VariableUseState variableUseState) { + return variableUseState != null && variableUseState != UNUSED; + } } } From 84d60b8baacb0048679e5ed171421d02f632660f Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 28 May 2012 15:21:40 +0400 Subject: [PATCH 19/24] check deeply inner local declarations added --- .../jet/lang/cfg/JetControlFlowProcessor.java | 3 +-- .../lang/cfg/pseudocode/PseudocodeImpl.java | 18 ++++++++++++------ .../checkInnerLocalDeclarations.jet | 12 ++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/controlFlowAnalysis/checkInnerLocalDeclarations.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index fa4d265e80f..4a2fd8bb33a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -54,7 +54,6 @@ public class JetControlFlowProcessor { this.trace = trace; } - //todo public Pseudocode generatePseudocode(@NotNull JetDeclaration subroutine) { Pseudocode pseudocode = generate(subroutine); ((PseudocodeImpl)pseudocode).postProcess(); @@ -64,7 +63,7 @@ public class JetControlFlowProcessor { return pseudocode; } - public Pseudocode generate(@NotNull JetDeclaration subroutine) { + private Pseudocode generate(@NotNull JetDeclaration subroutine) { builder.enterSubroutine(subroutine); if (subroutine instanceof JetDeclarationWithBody) { JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index 8eb651cf4a0..74beb128229 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -108,12 +108,18 @@ public class PseudocodeImpl implements Pseudocode { @Override public Set getLocalDeclarations() { if (localDeclarations == null) { - localDeclarations = Sets.newLinkedHashSet(); - //todo look recursively inside local declarations - for (Instruction instruction : instructions) { - if (instruction instanceof LocalDeclarationInstruction) { - localDeclarations.add((LocalDeclarationInstruction) instruction); - } + localDeclarations = getLocalDeclarations(this); + } + return localDeclarations; + } + + @NotNull + private static Set getLocalDeclarations(@NotNull Pseudocode pseudocode) { + Set localDeclarations = Sets.newHashSet(); + for (Instruction instruction : pseudocode.getInstructions()) { + if (instruction instanceof LocalDeclarationInstruction) { + localDeclarations.add((LocalDeclarationInstruction) instruction); + localDeclarations.addAll(getLocalDeclarations(((LocalDeclarationInstruction)instruction).getBody())); } } return localDeclarations; diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/checkInnerLocalDeclarations.jet b/compiler/testData/diagnostics/tests/controlFlowAnalysis/checkInnerLocalDeclarations.jet new file mode 100644 index 00000000000..422e57181f6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/checkInnerLocalDeclarations.jet @@ -0,0 +1,12 @@ +package c + +fun test() { + val x = 10 + fun inner1() { + fun inner2() { + fun inner3() { + val y = x + } + } + } +} \ No newline at end of file From a1714d99cf51ffe3dd12beb4d62c4f6a9f0b1723 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 28 May 2012 17:34:44 +0400 Subject: [PATCH 20/24] DependencyClassByFqNameResolver --- .../resolve/java/JavaDescriptorResolver.java | 12 +++++- ...ependencyClassByQualifiedNameResolver.java | 35 ++++++++++++++++++ ...ClassByQualifiedNameResolverDummyImpl.java | 37 +++++++++++++++++++ .../jet/di/AllInjectorsGenerator.java | 3 ++ .../di/InjectorForTopDownAnalyzerForJs.java | 3 ++ 5 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolver.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolverDummyImpl.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index e69bf8ee9af..05ab28ca5d2 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -49,7 +49,7 @@ import java.util.*; /** * @author abreslav */ -public class JavaDescriptorResolver { +public class JavaDescriptorResolver implements DependencyClassByQualifiedNameResolver { public static final Name JAVA_ROOT = Name.special(""); @@ -307,6 +307,11 @@ public class JavaDescriptorResolver { return clazz; } + @Override + public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) { + return resolveClass(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN); + } + private ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule, @NotNull List tasks) { if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) { // TODO: only if -$$TImpl class is created by Kotlin @@ -947,6 +952,11 @@ public class JavaDescriptorResolver { return scopeData.namespaceDescriptor; } + @Override + public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) { + return resolveNamespace(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN); + } + private NamespaceDescriptorParent resolveParentNamespace(FqName fqName) { if (fqName.isRoot()) { return FAKE_ROOT_MODULE; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolver.java new file mode 100644 index 00000000000..ea2a370c637 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolver.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.types; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.resolve.name.FqName; + +/** + * @author Stepan Koltsov + */ +public interface DependencyClassByQualifiedNameResolver { + + @Nullable + ClassDescriptor resolveClass(@NotNull FqName qualifiedName); + @Nullable + NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName); + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolverDummyImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolverDummyImpl.java new file mode 100644 index 00000000000..786e2a1df44 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/DependencyClassByQualifiedNameResolverDummyImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.types; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.resolve.name.FqName; + +/** + * @author Stepan Koltsov + */ +public class DependencyClassByQualifiedNameResolverDummyImpl implements DependencyClassByQualifiedNameResolver { + @Override + public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) { + return null; + } + + @Override + public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) { + return null; + } +} diff --git a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java index 2c026928cc6..5126603d4a0 100644 --- a/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java +++ b/injector-generator/src/org/jetbrains/jet/di/AllInjectorsGenerator.java @@ -31,6 +31,8 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.java.*; +import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; +import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolverDummyImpl; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; @@ -65,6 +67,7 @@ public class AllInjectorsGenerator { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(false); generateInjectorForTopDownAnalyzerCommon(generator); generator.addParameter(ModuleConfiguration.class); + generator.addField(DependencyClassByQualifiedNameResolverDummyImpl.class); generator.generate("js/js.translator/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerForJs"); } diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 7986b6c610f..f0dc9a7bc0c 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters; import org.jetbrains.jet.lang.resolve.ObservableBindingTrace; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.ModuleConfiguration; +import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolverDummyImpl; import org.jetbrains.jet.lang.resolve.DeclarationResolver; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; @@ -63,6 +64,7 @@ public class InjectorForTopDownAnalyzerForJs { private final ObservableBindingTrace observableBindingTrace; private final ModuleDescriptor moduleDescriptor; private final ModuleConfiguration moduleConfiguration; + private DependencyClassByQualifiedNameResolverDummyImpl dependencyClassByQualifiedNameResolverDummyImpl; private DeclarationResolver declarationResolver; private AnnotationResolver annotationResolver; private CallResolver callResolver; @@ -95,6 +97,7 @@ public class InjectorForTopDownAnalyzerForJs { this.observableBindingTrace = observableBindingTrace; this.moduleDescriptor = moduleDescriptor; this.moduleConfiguration = moduleConfiguration; + this.dependencyClassByQualifiedNameResolverDummyImpl = new DependencyClassByQualifiedNameResolverDummyImpl(); this.declarationResolver = new DeclarationResolver(); this.annotationResolver = new AnnotationResolver(); this.callResolver = new CallResolver(); From c2c45669f005f5f8684b30578704aaed149f57aa Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 28 May 2012 17:34:44 +0400 Subject: [PATCH 21/24] Validate parameters in fillInSubstitutionContext --- .../src/org/jetbrains/jet/lang/types/SubstitutionUtils.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java index 90f5e04380b..6fe27a072e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java @@ -95,6 +95,9 @@ public class SubstitutionUtils { } private static void fillInSubstitutionContext(List parameters, List contextArguments, Map parameterValues) { + if (parameters.size() != contextArguments.size()) { + throw new IllegalArgumentException("type parameter count != context arguments"); + } for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { TypeParameterDescriptor parameter = parameters.get(i); TypeProjection value = contextArguments.get(i); From b2cea09fcc3495ed0eda29b69e6eb28dee95f7ac Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 28 May 2012 17:34:45 +0400 Subject: [PATCH 22/24] move inner classes of CodegenContext into CodegenContexts --- .../jetbrains/jet/codegen/ClosureCodegen.java | 2 +- .../jetbrains/jet/codegen/CodegenContext.java | 209 +--------------- .../jet/codegen/CodegenContexts.java | 223 ++++++++++++++++++ .../jet/codegen/ExpressionCodegen.java | 10 +- .../jet/codegen/FunctionCodegen.java | 6 +- .../codegen/ImplementationBodyCodegen.java | 2 +- .../jet/codegen/NamespaceCodegen.java | 5 +- .../jet/codegen/ObjectOrClosureCodegen.java | 4 +- 8 files changed, 247 insertions(+), 214 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 18edab436a2..5ae0c455cbf 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -198,7 +198,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { private Type generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) { ClassDescriptor function = state.getInjector().getJetTypeMapper().getClosureAnnotator().classDescriptorForFunctionDescriptor(funDescriptor, name); - final CodegenContext.ClosureContext closureContext = context.intoClosure( + final CodegenContexts.ClosureContext closureContext = context.intoClosure( funDescriptor, function, name.getInternalName(), this, state.getInjector().getJetTypeMapper()); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); JvmMethodSignature jvmMethodSignature = invokeSignature(funDescriptor); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index d387a0f20b4..683f687e1e7 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -35,25 +35,6 @@ import java.util.LinkedHashMap; * @author alex.tkachman */ public abstract class CodegenContext { - public static final CodegenContext STATIC = new CodegenContext(null, OwnerKind.NAMESPACE, null, null) { - @Override - protected ClassDescriptor getThisDescriptor() { - return null; - } - - @Override - public boolean isStatic() { - return true; - } - - @Override - public String toString() { - return "ROOT"; - } - }; - - protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); - protected static final StackValue local1 = StackValue.local(1, JetTypeMapper.TYPE_OBJECT); private final DeclarationDescriptor contextType; @@ -121,31 +102,31 @@ public abstract class CodegenContext { } public CodegenContext intoNamespace(NamespaceDescriptor descriptor) { - return new NamespaceContext(descriptor, this); + return new CodegenContexts.NamespaceContext(descriptor, this); } public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) { - return new ClassContext(descriptor, kind, this, typeMapper); + return new CodegenContexts.ClassContext(descriptor, kind, this, typeMapper); } public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) { - return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper); + return new CodegenContexts.AnonymousClassContext(descriptor, kind, this, closure, typeMapper); } - public MethodContext intoFunction(FunctionDescriptor descriptor) { - return new MethodContext(descriptor, getContextKind(), this); + public CodegenContexts.MethodContext intoFunction(FunctionDescriptor descriptor) { + return new CodegenContexts.MethodContext(descriptor, getContextKind(), this); } - public ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) { + public CodegenContexts.ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) { if(descriptor == null) { descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.emptyList(), true) .initialize(Collections.emptyList(), Collections.emptyList(), Visibilities.PUBLIC); } - return new ConstructorContext(descriptor, getContextKind(), this, typeMapper); + return new CodegenContexts.ConstructorContext(descriptor, getContextKind(), this, typeMapper); } - public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) { - return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper); + public CodegenContexts.ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) { + return new CodegenContexts.ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper); } public FrameMap prepareFrame(JetTypeMapper mapper) { @@ -190,7 +171,7 @@ public abstract class CodegenContext { } public int getTypeInfoConstantIndex(JetType type) { - if (parentContext != STATIC) { return parentContext.getTypeInfoConstantIndex(type); } + if (parentContext != CodegenContexts.STATIC) { return parentContext.getTypeInfoConstantIndex(type); } if(typeInfoConstants == null) { typeInfoConstants = new LinkedHashMap(); @@ -280,174 +261,4 @@ public abstract class CodegenContext { this.accessors.putAll(accessors); } } - - public abstract static class ReceiverContext extends CodegenContext { - final CallableDescriptor receiverDescriptor; - - public ReceiverContext(CallableDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) { - super(contextType, contextKind, parentContext, closureCodegen); - receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType : null; - } - - @Override - protected CallableDescriptor getReceiverDescriptor() { - return receiverDescriptor; - } - } - - public static class MethodContext extends ReceiverContext { - public MethodContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) { - super(contextType instanceof PropertyAccessorDescriptor ? ((PropertyAccessorDescriptor)contextType).getCorrespondingProperty() : contextType, contextKind, parentContext, null); - } - - @Override - protected ClassDescriptor getThisDescriptor() { - return getParentContext().getThisDescriptor(); - } - - public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) { - return getParentContext().lookupInContext(d, v, result); - } - - public Type enclosingClassType(JetTypeMapper typeMapper) { - return getParentContext().enclosingClassType(typeMapper); - } - - @Override - public boolean isStatic() { - return getParentContext().isStatic(); - } - - protected StackValue getOuterExpression(StackValue prefix) { - return getParentContext().getOuterExpression(prefix); - } - - @Override - public String toString() { - return "Method: " + getContextDescriptor(); - } - } - - public static class ConstructorContext extends MethodContext { - public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) { - super(contextType, kind, parent); - - final Type type = enclosingClassType(typeMapper); - outerExpression = type != null - ? local1 - : null; - } - - protected StackValue getOuterExpression(StackValue prefix) { - return outerExpression; - } - - @Override - public String toString() { - return "Constructor: " + getContextDescriptor().getName(); - } - } - - public static class ClassContext extends CodegenContext { - public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) { - super(contextType, contextKind, parentContext, null); - - final Type type = enclosingClassType(typeMapper); - outerExpression = type != null - ? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false) - : null; - } - - @Override - protected ClassDescriptor getThisDescriptor() { - return (ClassDescriptor) getContextDescriptor(); - } - - @Override - public boolean isStatic() { - return false; - } - } - - public static class AnonymousClassContext extends CodegenContext { - public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) { - super(contextType, contextKind, parentContext, closure); - - final Type type = enclosingClassType(typeMapper); - Type owner = closure.state.getInjector().getJetTypeMapper().mapType(contextType.getDefaultType(), MapTypeMode.IMPL); - outerExpression = type != null - ? StackValue.field(type, owner.getInternalName(), "this$0", false) - : null; - } - - @Override - protected ClassDescriptor getThisDescriptor() { - return (ClassDescriptor) getContextDescriptor(); - } - - @Override - public boolean isStatic() { - return false; - } - - @Override - public String toString() { - return "Anonymous: " + getThisDescriptor(); - } - } - - public static class ClosureContext extends ReceiverContext { - private ClassDescriptor classDescriptor; - - public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName, JetTypeMapper typeMapper) { - super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen); - this.classDescriptor = classDescriptor; - - final Type type = enclosingClassType(typeMapper); - outerExpression = type != null - ? StackValue.field(type, internalClassName, "this$0", false) - : null; - } - - @Override - protected ClassDescriptor getThisDescriptor() { - return classDescriptor; - } - - @Override - public DeclarationDescriptor getContextDescriptor() { - return classDescriptor; - } - - @Override - public boolean isStatic() { - return false; - } - - @Override - public String toString() { - return "Closure: " + classDescriptor; - } - } - - public static class NamespaceContext extends CodegenContext { - public NamespaceContext(NamespaceDescriptor contextType, CodegenContext parent) { - super(contextType, OwnerKind.NAMESPACE, parent, null); - } - - @Override - protected ClassDescriptor getThisDescriptor() { - return null; - } - - @Override - public boolean isStatic() { - return true; - } - - @Override - public String toString() { - return "Namespace: " + getContextDescriptor().getName(); - } - } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java new file mode 100644 index 00000000000..283d26ff222 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContexts.java @@ -0,0 +1,223 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +/** + * @author Stepan Koltsov + */ +public class CodegenContexts { + public static final CodegenContext STATIC = new CodegenContext(null, OwnerKind.NAMESPACE, null, null) { + @Override + protected ClassDescriptor getThisDescriptor() { + return null; + } + + @Override + public boolean isStatic() { + return true; + } + + @Override + public String toString() { + return "ROOT"; + } + }; + protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); + protected static final StackValue local1 = StackValue.local(1, JetTypeMapper.TYPE_OBJECT); + + public abstract static class ReceiverContext extends CodegenContext { + final CallableDescriptor receiverDescriptor; + + public ReceiverContext(CallableDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) { + super(contextType, contextKind, parentContext, closureCodegen); + receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType : null; + } + + @Override + protected CallableDescriptor getReceiverDescriptor() { + return receiverDescriptor; + } + } + + public static class MethodContext extends ReceiverContext { + public MethodContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) { + super(contextType instanceof PropertyAccessorDescriptor ? ((PropertyAccessorDescriptor)contextType).getCorrespondingProperty() : contextType, contextKind, parentContext, null); + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return getParentContext().getThisDescriptor(); + } + + public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) { + return getParentContext().lookupInContext(d, v, result); + } + + public Type enclosingClassType(JetTypeMapper typeMapper) { + return getParentContext().enclosingClassType(typeMapper); + } + + @Override + public boolean isStatic() { + return getParentContext().isStatic(); + } + + protected StackValue getOuterExpression(StackValue prefix) { + return getParentContext().getOuterExpression(prefix); + } + + @Override + public String toString() { + return "Method: " + getContextDescriptor(); + } + } + + public static class ConstructorContext extends MethodContext { + public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) { + super(contextType, kind, parent); + + final Type type = enclosingClassType(typeMapper); + outerExpression = type != null + ? local1 + : null; + } + + protected StackValue getOuterExpression(StackValue prefix) { + return outerExpression; + } + + @Override + public String toString() { + return "Constructor: " + getContextDescriptor().getName(); + } + } + + public static class ClassContext extends CodegenContext { + public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) { + super(contextType, contextKind, parentContext, null); + + final Type type = enclosingClassType(typeMapper); + outerExpression = type != null + ? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false) + : null; + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return (ClassDescriptor) getContextDescriptor(); + } + + @Override + public boolean isStatic() { + return false; + } + } + + public static class AnonymousClassContext extends CodegenContext { + public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) { + super(contextType, contextKind, parentContext, closure); + + final Type type = enclosingClassType(typeMapper); + Type owner = closure.state.getInjector().getJetTypeMapper().mapType(contextType.getDefaultType(), MapTypeMode.IMPL); + outerExpression = type != null + ? StackValue.field(type, owner.getInternalName(), "this$0", false) + : null; + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return (ClassDescriptor) getContextDescriptor(); + } + + @Override + public boolean isStatic() { + return false; + } + + @Override + public String toString() { + return "Anonymous: " + getThisDescriptor(); + } + } + + public static class ClosureContext extends ReceiverContext { + private ClassDescriptor classDescriptor; + + public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName, JetTypeMapper typeMapper) { + super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen); + this.classDescriptor = classDescriptor; + + final Type type = enclosingClassType(typeMapper); + outerExpression = type != null + ? StackValue.field(type, internalClassName, "this$0", false) + : null; + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return classDescriptor; + } + + @Override + public DeclarationDescriptor getContextDescriptor() { + return classDescriptor; + } + + @Override + public boolean isStatic() { + return false; + } + + @Override + public String toString() { + return "Closure: " + classDescriptor; + } + } + + public static class NamespaceContext extends CodegenContext { + public NamespaceContext(NamespaceDescriptor contextType, CodegenContext parent) { + super(contextType, OwnerKind.NAMESPACE, parent, null); + } + + @Override + protected ClassDescriptor getThisDescriptor() { + return null; + } + + @Override + public boolean isStatic() { + return true; + } + + @Override + public String toString() { + return "Namespace: " + getContextDescriptor().getName(); + } + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index fb370463936..3f82f7db800 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1162,7 +1162,7 @@ public class ExpressionCodegen extends JetVisitor { boolean isStatic = containingDeclaration instanceof NamespaceDescriptor; propertyDescriptor = propertyDescriptor.getOriginal(); boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) || - (context.getParentContext() instanceof CodegenContext.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration) + (context.getParentContext() instanceof CodegenContexts.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration) && contextKind() != OwnerKind.TRAIT_IMPL; Method getter; Method setter; @@ -1438,8 +1438,8 @@ public class ExpressionCodegen extends JetVisitor { } private StackValue generateReceiver(DeclarationDescriptor provided) { - assert context instanceof CodegenContext.ReceiverContext; - CodegenContext.ReceiverContext cur = (CodegenContext.ReceiverContext) context; + assert context instanceof CodegenContexts.ReceiverContext; + CodegenContexts.ReceiverContext cur = (CodegenContexts.ReceiverContext) context; if (cur.getReceiverDescriptor() == provided) { StackValue result = cur.getReceiverExpression(typeMapper); return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); @@ -1458,7 +1458,7 @@ public class ExpressionCodegen extends JetVisitor { cur = context; StackValue result = StackValue.local(0, TYPE_OBJECT); while (cur != null) { - if(cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) + if(cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext)) cur = cur.getParentContext(); if (DescriptorUtils.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) { @@ -1474,7 +1474,7 @@ public class ExpressionCodegen extends JetVisitor { result = cur.getOuterExpression(result); - if(cur instanceof CodegenContext.ConstructorContext) { + if(cur instanceof CodegenContexts.ConstructorContext) { cur = cur.getParentContext(); } cur = cur.getParentContext(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 4a3d6788223..287328ea27a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -69,7 +69,7 @@ public class FunctionCodegen { JvmMethodSignature jvmMethod, boolean needJetAnnotations, @Nullable String propertyTypeSignature, FunctionDescriptor functionDescriptor) { - CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor); + CodegenContexts.MethodContext funContext = owner.intoFunction(functionDescriptor); final JetExpression bodyExpression = f.getBodyExpression(); generatedMethod(bodyExpression, jvmMethod, needJetAnnotations, propertyTypeSignature, funContext, functionDescriptor, f); @@ -78,7 +78,7 @@ public class FunctionCodegen { private void generatedMethod(JetExpression bodyExpressions, JvmMethodSignature jvmSignature, boolean needJetAnnotations, @Nullable String propertyTypeSignature, - CodegenContext.MethodContext context, + CodegenContexts.MethodContext context, FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun ) @@ -301,7 +301,7 @@ public class FunctionCodegen { } } - static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, @Nullable FunctionDescriptor functionDescriptor, OwnerKind kind) { + static void generateDefaultIfNeeded(CodegenContexts.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, @Nullable FunctionDescriptor functionDescriptor, OwnerKind kind) { DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration(); if(kind != OwnerKind.TRAIT_IMPL) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 9d0452be3f3..3d90db50b95 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -449,7 +449,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); - CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper); + CodegenContexts.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper); JvmMethodSignature constructorMethod; CallableMethod callableMethod; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index fe0faeec34e..53348ac9506 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -23,7 +23,6 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.name.FqName; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.objectweb.asm.MethodVisitor; @@ -57,7 +56,7 @@ public class NamespaceCodegen { public void generate(JetFile file) { NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file); - final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); + final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor); final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state); final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state); @@ -100,7 +99,7 @@ public class NamespaceCodegen { mv.visitCode(); FrameMap frameMap = new FrameMap(); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state); + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.STATIC, state); for (JetDeclaration declaration : namespace.getDeclarations()) { if (declaration instanceof JetProperty) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java index a670be29554..e0666f20af1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java @@ -106,9 +106,9 @@ public class ObjectOrClosureCodegen { FunctionDescriptor fd = (FunctionDescriptor) d; // we generate method - assert context instanceof CodegenContext.ReceiverContext; + assert context instanceof CodegenContexts.ReceiverContext; - CodegenContext.ReceiverContext fcontext = (CodegenContext.ReceiverContext) context; + CodegenContexts.ReceiverContext fcontext = (CodegenContexts.ReceiverContext) context; if(fcontext.getReceiverDescriptor() != fd) return null; From 2165d5b76594b7ac27c90ef239a0d52566a79b81 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 28 May 2012 18:37:03 +0400 Subject: [PATCH 23/24] fix for 'JetControlFlowTest.testLocalDeclarations' test --- .../org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index 74beb128229..1106d56f9a2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -115,7 +115,7 @@ public class PseudocodeImpl implements Pseudocode { @NotNull private static Set getLocalDeclarations(@NotNull Pseudocode pseudocode) { - Set localDeclarations = Sets.newHashSet(); + Set localDeclarations = Sets.newLinkedHashSet(); for (Instruction instruction : pseudocode.getInstructions()) { if (instruction instanceof LocalDeclarationInstruction) { localDeclarations.add((LocalDeclarationInstruction) instruction); From e4007992c66f9820303bc6be666053643acc780d Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 28 May 2012 20:02:19 +0400 Subject: [PATCH 24/24] Extract interface: TypeParameterDescriptor A lot of code relied on these descriptors being mutable. In most cases I managed to work around this, but there're still are casts to raw List necessary in one or two places --- .../jetbrains/jet/codegen/CodegenContext.java | 2 +- .../jetbrains/jet/codegen/CodegenUtil.java | 2 +- .../jet/codegen/ExpressionCodegen.java | 4 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 6 +- .../resolve/java/JavaDescriptorResolver.java | 16 +- ...peVariableResolverFromTypeDescriptors.java | 1 - .../resolve/java/TypeVariableResolvers.java | 7 +- .../lang/descriptors/ClassDescriptorImpl.java | 4 +- .../descriptors/FunctionDescriptorImpl.java | 4 +- .../descriptors/FunctionDescriptorUtil.java | 2 +- .../lang/descriptors/PropertyDescriptor.java | 6 +- .../SimpleFunctionDescriptorImpl.java | 2 +- .../descriptors/TypeParameterDescriptor.java | 238 +-------------- .../TypeParameterDescriptorImpl.java | 275 ++++++++++++++++++ .../jet/lang/resolve/DescriptorResolver.java | 27 +- .../jet/lang/resolve/DescriptorUtils.java | 2 +- .../jet/lang/resolve/OverridingUtil.java | 2 +- .../lang/resolve/TypeHierarchyResolver.java | 4 +- .../jet/lang/resolve/TypeResolver.java | 2 +- .../ConstraintSystemWithPriorities.java | 5 +- .../jet/lang/types/DescriptorSubstitutor.java | 3 +- .../jetbrains/jet/lang/types/ErrorUtils.java | 4 +- .../jet/lang/types/SubstitutionUtils.java | 3 +- .../jet/lang/types/TypeConstructorImpl.java | 2 +- .../jetbrains/jet/lang/types/TypeUtils.java | 7 +- .../ClosureExpressionsTypingVisitor.java | 2 +- .../lang/types/lang/JetStandardClasses.java | 10 +- .../jet/resolve/DescriptorRenderer.java | 2 +- .../jet/types/JetTypeCheckerTest.java | 2 +- .../jet/plugin/JetDescriptorIconProvider.java | 2 +- .../completion/JetCompletionContributor.java | 2 +- 31 files changed, 357 insertions(+), 293 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptorImpl.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index 683f687e1e7..11969ba40d7 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -223,7 +223,7 @@ public abstract class CodegenContext { CallableMemberDescriptor.Kind.DECLARATION ); JetType receiverType = pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null; - myAccessor.setType(pd.getType(), Collections.emptyList(), pd.getExpectedThisObject(), receiverType); + myAccessor.setType(pd.getType(), Collections.emptyList(), pd.getExpectedThisObject(), receiverType); PropertyGetterDescriptor pgd = new PropertyGetterDescriptor( myAccessor, Collections.emptyList(), myAccessor.getModality(), diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index caaf653c39b..be95711e65a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -54,7 +54,7 @@ public class CodegenUtil { invokeDescriptor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, fd.getExpectedThisObject(), - Collections.emptyList(), + Collections.emptyList(), fd.getValueParameters(), fd.getReturnType(), Modality.FINAL, diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 3f82f7db800..9890c1183de 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1093,7 +1093,7 @@ public class ExpressionCodegen extends JetVisitor { } } - if (descriptor instanceof TypeParameterDescriptor) { + if (descriptor instanceof TypeParameterDescriptorImpl) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); v.checkcast(asmType(typeParameterDescriptor.getClassObjectType())); @@ -2614,7 +2614,7 @@ If finally block is present, its last expression is the value of try expression. JetExpression left = expression.getLeft(); JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left); DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); - if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { + if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptorImpl) { StackValue value = genQualified(receiver, left); value.put(JetTypeMapper.boxType(value.type), v); assert leftType != null; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index d1b3807da64..71bc4f14ec5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -463,7 +463,7 @@ public class JetTypeMapper { return asmType; } - if (descriptor instanceof TypeParameterDescriptor) { + if (descriptor instanceof TypeParameterDescriptorImpl) { Type type = mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind); if (signatureVisitor != null) { @@ -722,7 +722,7 @@ public class JetTypeMapper { signatureVisitor.writeInterfaceBoundEnd(); } } - if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { + if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) { signatureVisitor.writeInterfaceBound(); mapType(jetType, signatureVisitor, MapTypeMode.TYPE_PARAMETER); signatureVisitor.writeInterfaceBoundEnd(); @@ -966,7 +966,7 @@ public class JetTypeMapper { public boolean isGenericsArray(JetType type) { DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); - if(declarationDescriptor instanceof TypeParameterDescriptor) + if(declarationDescriptor instanceof TypeParameterDescriptorImpl) return true; if(standardLibrary.getArray().equals(declarationDescriptor)) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 05ab28ca5d2..506ce076cac 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -107,14 +107,14 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes @NotNull private final TypeParameterDescriptorOrigin origin; @NotNull - final TypeParameterDescriptor descriptor; + final TypeParameterDescriptorImpl descriptor; final PsiTypeParameter psiTypeParameter; @Nullable private final List upperBoundsForKotlin; @Nullable private final List lowerBoundsForKotlin; - private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptor descriptor, @NotNull PsiTypeParameter psiTypeParameter) { + private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptorImpl descriptor, @NotNull PsiTypeParameter psiTypeParameter) { this.origin = TypeParameterDescriptorOrigin.JAVA; this.descriptor = descriptor; this.psiTypeParameter = psiTypeParameter; @@ -122,7 +122,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes this.lowerBoundsForKotlin = null; } - private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptor descriptor, @NotNull PsiTypeParameter psiTypeParameter, + private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptorImpl descriptor, @NotNull PsiTypeParameter psiTypeParameter, List upperBoundsForKotlin, List lowerBoundsForKotlin) { this.origin = TypeParameterDescriptorOrigin.KOTLIN; this.descriptor = descriptor; @@ -608,10 +608,10 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes @NotNull private final TypeVariableResolver typeVariableResolver; @NotNull - private final TypeParameterDescriptor typeParameterDescriptor; + private final TypeParameterDescriptorImpl typeParameterDescriptor; protected JetSignatureTypeParameterVisitor(PsiTypeParameterListOwner psiOwner, - String name, TypeVariableResolver typeVariableResolver, TypeParameterDescriptor typeParameterDescriptor) + String name, TypeVariableResolver typeVariableResolver, TypeParameterDescriptorImpl typeParameterDescriptor) { if (name.isEmpty()) { throw new IllegalStateException(); @@ -687,7 +687,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes @Override public JetSignatureVisitor visitFormalTypeParameter(final String name, final TypeInfoVariance variance, boolean reified) { - TypeParameterDescriptor typeParameter = TypeParameterDescriptor.createForFurtherModification( + TypeParameterDescriptorImpl typeParameter = TypeParameterDescriptorImpl.createForFurtherModification( containingDeclaration, Collections.emptyList(), // TODO: wrong reified, @@ -762,7 +762,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes @NotNull private TypeParameterDescriptorInitialization makeUninitializedTypeParameter(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter psiTypeParameter) { - TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification( + TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification( containingDeclaration, Collections.emptyList(), // TODO false, @@ -774,7 +774,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes } private void initializeTypeParameter(TypeParameterDescriptorInitialization typeParameter, TypeVariableResolver typeVariableByPsiResolver) { - TypeParameterDescriptor typeParameterDescriptor = typeParameter.descriptor; + TypeParameterDescriptorImpl typeParameterDescriptor = typeParameter.descriptor; if (typeParameter.origin == TypeParameterDescriptorOrigin.KOTLIN) { List upperBounds = typeParameter.upperBoundsForKotlin; if (upperBounds.size() == 0){ diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java index ed1f6235fff..aedd1e8bef1 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolverFromTypeDescriptors.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.resolve.java; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java index 3a63089762c..858625e4c93 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeVariableResolvers.java @@ -17,12 +17,7 @@ package org.jetbrains.jet.lang.resolve.java; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import java.util.ArrayList; import java.util.List; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java index b3a0d6974ee..0dde08e8498 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java @@ -48,7 +48,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl } public final ClassDescriptorImpl initialize(boolean sealed, - @NotNull List typeParameters, + @NotNull List typeParameters, @NotNull Collection supertypes, @NotNull JetScope memberDeclarations, @NotNull Set constructors, @@ -57,7 +57,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl } public final ClassDescriptorImpl initialize(boolean sealed, - @NotNull List typeParameters, + @NotNull List typeParameters, @NotNull Collection supertypes, @NotNull JetScope memberDeclarations, @NotNull Set constructors, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index 69216fca3f0..fcc486e9d3e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -77,12 +77,12 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i protected FunctionDescriptorImpl initialize( @Nullable JetType receiverType, @NotNull ReceiverDescriptor expectedThisObject, - @NotNull List typeParameters, + @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, @Nullable Modality modality, @NotNull Visibility visibility) { - this.typeParameters = typeParameters; + this.typeParameters = Lists.newArrayList(typeParameters); this.unsubstitutedValueParameters = unsubstitutedValueParameters; this.unsubstitutedReturnType = unsubstitutedReturnType; this.modality = modality; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java index e9e543a1fe5..8044d6b2dde 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java @@ -126,7 +126,7 @@ public class FunctionDescriptorUtil { assert JetStandardClasses.isFunctionType(functionType); functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType), expectedThisObject, - Collections.emptyList(), + Collections.emptyList(), JetStandardClasses.getValueParameters(functionDescriptor, functionType), JetStandardClasses.getReturnTypeFromFunctionType(functionType), modality, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java index 4a535c807c0..88058260e6e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java @@ -112,17 +112,17 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab setType(outType, Collections.emptyList(), expectedThisObject, receiverType); } - public void setType(@NotNull JetType outType, @NotNull List typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @Nullable JetType receiverType) { + public void setType(@NotNull JetType outType, @NotNull List typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @Nullable JetType receiverType) { ReceiverDescriptor receiver = receiverType == null ? NO_RECEIVER : new ExtensionReceiver(this, receiverType); setType(outType, typeParameters, expectedThisObject, receiver); } - public void setType(@NotNull JetType outType, @NotNull List typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @NotNull ReceiverDescriptor receiver) { + public void setType(@NotNull JetType outType, @NotNull List typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @NotNull ReceiverDescriptor receiver) { setOutType(outType); - this.typeParameters = typeParameters; + this.typeParameters = Lists.newArrayList(typeParameters); this.receiver = receiver; this.expectedThisObject = expectedThisObject; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/SimpleFunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/SimpleFunctionDescriptorImpl.java index 57d84e60de1..7c2cda46d0c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/SimpleFunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/SimpleFunctionDescriptorImpl.java @@ -54,7 +54,7 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme public SimpleFunctionDescriptorImpl initialize( @Nullable JetType receiverType, @NotNull ReceiverDescriptor expectedThisObject, - @NotNull List typeParameters, + @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, @Nullable Modality modality, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java index 66b588e80a7..07afc2a3866 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java @@ -16,251 +16,45 @@ package org.jetbrains.jet.lang.descriptors; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.name.Name; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; -import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; -import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lang.types.checker.JetTypeChecker; -import org.jetbrains.jet.lang.types.lang.JetStandardClasses; -import org.jetbrains.jet.resolve.DescriptorRenderer; -import org.jetbrains.jet.util.lazy.LazyValue; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeConstructor; +import org.jetbrains.jet.lang.types.TypeSubstitutor; +import org.jetbrains.jet.lang.types.Variance; -import java.util.Collections; -import java.util.List; import java.util.Set; /** * @author abreslav */ -public class TypeParameterDescriptor extends DeclarationDescriptorImpl implements ClassifierDescriptor { - public static TypeParameterDescriptor createWithDefaultBound( - @NotNull DeclarationDescriptor containingDeclaration, - @NotNull List annotations, - boolean reified, - @NotNull Variance variance, - @NotNull Name name, - int index) { - TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index); - typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound()); - typeParameterDescriptor.setInitialized(); - return typeParameterDescriptor; - } +public interface TypeParameterDescriptor extends ClassifierDescriptor { + boolean isReified(); - public static TypeParameterDescriptor createForFurtherModification( - @NotNull DeclarationDescriptor containingDeclaration, - @NotNull List annotations, - boolean reified, - @NotNull Variance variance, - @NotNull Name name, - int index) { - return new TypeParameterDescriptor(containingDeclaration, annotations, reified, variance, name, index); - } - - // 0-based - private final int index; - private final Variance variance; - private final Set upperBounds; - private JetType upperBoundsAsType; - private final TypeConstructor typeConstructor; - private JetType defaultType; - private final Set classObjectUpperBounds = Sets.newLinkedHashSet(); - private JetType classObjectBoundsAsType; - - private final boolean reified; - - private boolean initialized = false; - - private TypeParameterDescriptor( - @NotNull DeclarationDescriptor containingDeclaration, - @NotNull List annotations, - boolean reified, - @NotNull Variance variance, - @NotNull Name name, - int index) { - super(containingDeclaration, annotations, name); - this.index = index; - this.variance = variance; - this.upperBounds = Sets.newLinkedHashSet(); - this.reified = reified; - // TODO: Should we actually pass the annotations on to the type constructor? - this.typeConstructor = new TypeConstructorImpl( - this, - annotations, - false, - name.getName(), - Collections.emptyList(), - upperBounds); - } - - private void checkInitialized() { - if (!initialized) { - throw new IllegalStateException("Type parameter descriptor in not initialized: " + nameForAssertions()); - } - } - - private void checkUninitialized() { - if (initialized) { - throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions()); - } - } - - private String nameForAssertions() { - DeclarationDescriptor owner = getContainingDeclaration(); - return getName() + " declared in " + (owner == null ? "" : owner.getName()); - } - - public void setInitialized() { - checkUninitialized(); - initialized = true; - } - - public boolean isReified() { - checkInitialized(); - return reified; - } - - public Variance getVariance() { - checkInitialized(); - return variance; - } - - public void addUpperBound(@NotNull JetType bound) { - checkUninitialized(); - doAddUpperBound(bound); - } - - private void doAddUpperBound(JetType bound) { - upperBounds.add(bound); // TODO : Duplicates? - } - - public void addDefaultUpperBound() { - checkUninitialized(); - - if (upperBounds.isEmpty()) { - doAddUpperBound(JetStandardClasses.getDefaultBound()); - } - } + Variance getVariance(); @NotNull - public Set getUpperBounds() { - checkInitialized(); - return upperBounds; - } + Set getUpperBounds(); @NotNull - public JetType getUpperBoundsAsType() { - checkInitialized(); - if (upperBoundsAsType == null) { - assert upperBounds != null : "Upper bound list is null in " + getName(); - assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName(); - upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); - if (upperBoundsAsType == null) { - upperBoundsAsType = JetStandardClasses.getNothingType(); - } - } - return upperBoundsAsType; - } + JetType getUpperBoundsAsType(); @NotNull - public Set getLowerBounds() { - //checkInitialized(); - return Collections.singleton(JetStandardClasses.getNothingType()); - } + Set getLowerBounds(); @NotNull - public JetType getLowerBoundsAsType() { - checkInitialized(); - return JetStandardClasses.getNothingType(); - } - - + JetType getLowerBoundsAsType(); + @NotNull @Override - public TypeConstructor getTypeConstructor() { - //checkInitialized(); - return typeConstructor; - } - - @Override - public String toString() { - try { - return DescriptorRenderer.TEXT.render(this); - } catch (Exception e) { - return this.getClass().getName() + "@" + System.identityHashCode(this); - } - } + TypeConstructor getTypeConstructor(); @NotNull @Override @Deprecated // Use the static method TypeParameterDescriptor.substitute() - public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) { - throw new UnsupportedOperationException(); - } + TypeParameterDescriptor substitute(TypeSubstitutor substitutor); - @Override - public R accept(DeclarationDescriptorVisitor visitor, D data) { - checkInitialized(); - return visitor.visitTypeParameterDescriptor(this, data); - } + int getIndex(); @NotNull - @Override - public JetType getDefaultType() { - //checkInitialized(); - if (defaultType == null) { - defaultType = new JetTypeImpl( - Collections.emptyList(), - getTypeConstructor(), - TypeUtils.hasNullableLowerBound(this), - Collections.emptyList(), - new LazyScopeAdapter(new LazyValue() { - @Override - protected JetScope compute() { - return getUpperBoundsAsType().getMemberScope(); - } - })); - } - return defaultType; - } - - @Override - public JetType getClassObjectType() { - checkInitialized(); - if (classObjectUpperBounds.isEmpty()) return null; - - if (classObjectBoundsAsType == null) { - classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds); - if (classObjectBoundsAsType == null) { - classObjectBoundsAsType = JetStandardClasses.getNothingType(); - } - } - return classObjectBoundsAsType; - } - - @Override - public boolean isClassObjectAValue() { - return true; - } - - public void addClassObjectBound(@NotNull JetType bound) { - checkUninitialized(); - classObjectUpperBounds.add(bound); // TODO : Duplicates? - } - - public int getIndex() { - checkInitialized(); - return index; - } - - @NotNull - public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) { - TypeParameterDescriptor copy = new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index); - copy.upperBounds.addAll(this.upperBounds); - copy.initialized = this.initialized; - return copy; - } + TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptorImpl.java new file mode 100644 index 00000000000..1ccd4ff68ee --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptorImpl.java @@ -0,0 +1,275 @@ +/* + * Copyright 2010-2012 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 org.jetbrains.jet.lang.descriptors; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; +import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import org.jetbrains.jet.resolve.DescriptorRenderer; +import org.jetbrains.jet.util.lazy.LazyValue; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author abreslav + */ +public class TypeParameterDescriptorImpl extends DeclarationDescriptorImpl implements TypeParameterDescriptor { + public static TypeParameterDescriptor createWithDefaultBound( + @NotNull DeclarationDescriptor containingDeclaration, + @NotNull List annotations, + boolean reified, + @NotNull Variance variance, + @NotNull Name name, + int index) { + TypeParameterDescriptorImpl typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index); + typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound()); + typeParameterDescriptor.setInitialized(); + return typeParameterDescriptor; + } + + public static TypeParameterDescriptorImpl createForFurtherModification( + @NotNull DeclarationDescriptor containingDeclaration, + @NotNull List annotations, + boolean reified, + @NotNull Variance variance, + @NotNull Name name, + int index) { + return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index); + } + + // 0-based + private final int index; + private final Variance variance; + private final Set upperBounds; + private JetType upperBoundsAsType; + private final TypeConstructor typeConstructor; + private JetType defaultType; + private final Set classObjectUpperBounds = Sets.newLinkedHashSet(); + private JetType classObjectBoundsAsType; + + private final boolean reified; + + private boolean initialized = false; + + private TypeParameterDescriptorImpl( + @NotNull DeclarationDescriptor containingDeclaration, + @NotNull List annotations, + boolean reified, + @NotNull Variance variance, + @NotNull Name name, + int index) { + super(containingDeclaration, annotations, name); + this.index = index; + this.variance = variance; + this.upperBounds = Sets.newLinkedHashSet(); + this.reified = reified; + // TODO: Should we actually pass the annotations on to the type constructor? + this.typeConstructor = new TypeConstructorImpl( + this, + annotations, + false, + name.getName(), + Collections.emptyList(), + upperBounds); + } + + private void checkInitialized() { + if (!initialized) { + throw new IllegalStateException("Type parameter descriptor in not initialized: " + nameForAssertions()); + } + } + + private void checkUninitialized() { + if (initialized) { + throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions()); + } + } + + private String nameForAssertions() { + DeclarationDescriptor owner = getContainingDeclaration(); + return getName() + " declared in " + (owner == null ? "" : owner.getName()); + } + + public void setInitialized() { + checkUninitialized(); + initialized = true; + } + + @Override + public boolean isReified() { + checkInitialized(); + return reified; + } + + @Override + public Variance getVariance() { + checkInitialized(); + return variance; + } + + public void addUpperBound(@NotNull JetType bound) { + checkUninitialized(); + doAddUpperBound(bound); + } + + private void doAddUpperBound(JetType bound) { + upperBounds.add(bound); // TODO : Duplicates? + } + + public void addDefaultUpperBound() { + checkUninitialized(); + + if (upperBounds.isEmpty()) { + doAddUpperBound(JetStandardClasses.getDefaultBound()); + } + } + + @Override + @NotNull + public Set getUpperBounds() { + checkInitialized(); + return upperBounds; + } + + @Override + @NotNull + public JetType getUpperBoundsAsType() { + checkInitialized(); + if (upperBoundsAsType == null) { + assert upperBounds != null : "Upper bound list is null in " + getName(); + assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName(); + upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); + if (upperBoundsAsType == null) { + upperBoundsAsType = JetStandardClasses.getNothingType(); + } + } + return upperBoundsAsType; + } + + @Override + @NotNull + public Set getLowerBounds() { + //checkInitialized(); + return Collections.singleton(JetStandardClasses.getNothingType()); + } + + @Override + @NotNull + public JetType getLowerBoundsAsType() { + checkInitialized(); + return JetStandardClasses.getNothingType(); + } + + + @NotNull + @Override + public TypeConstructor getTypeConstructor() { + //checkInitialized(); + return typeConstructor; + } + + @Override + public String toString() { + try { + return DescriptorRenderer.TEXT.render(this); + } catch (Exception e) { + return this.getClass().getName() + "@" + System.identityHashCode(this); + } + } + + @NotNull + @Override + @Deprecated // Use the static method TypeParameterDescriptor.substitute() + public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) { + throw new UnsupportedOperationException(); + } + + @Override + public R accept(DeclarationDescriptorVisitor visitor, D data) { + checkInitialized(); + return visitor.visitTypeParameterDescriptor(this, data); + } + + @NotNull + @Override + public JetType getDefaultType() { + //checkInitialized(); + if (defaultType == null) { + defaultType = new JetTypeImpl( + Collections.emptyList(), + getTypeConstructor(), + TypeUtils.hasNullableLowerBound(this), + Collections.emptyList(), + new LazyScopeAdapter(new LazyValue() { + @Override + protected JetScope compute() { + return getUpperBoundsAsType().getMemberScope(); + } + })); + } + return defaultType; + } + + @Override + public JetType getClassObjectType() { + checkInitialized(); + if (classObjectUpperBounds.isEmpty()) return null; + + if (classObjectBoundsAsType == null) { + classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds); + if (classObjectBoundsAsType == null) { + classObjectBoundsAsType = JetStandardClasses.getNothingType(); + } + } + return classObjectBoundsAsType; + } + + @Override + public boolean isClassObjectAValue() { + return true; + } + + public void addClassObjectBound(@NotNull JetType bound) { + checkUninitialized(); + classObjectUpperBounds.add(bound); // TODO : Duplicates? + } + + @Override + public int getIndex() { + checkInitialized(); + return index; + } + + @Override + @NotNull + public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) { + TypeParameterDescriptorImpl + copy = new TypeParameterDescriptorImpl(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index); + copy.upperBounds.addAll(this.upperBounds); + copy.initialized = this.initialized; + return copy; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 73d69e2a067..0c4ed63ac33 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -79,7 +79,7 @@ public class DescriptorResolver { List typeParameters = Lists.newArrayList(); int index = 0; for (JetTypeParameter typeParameter : classElement.getTypeParameters()) { - TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification( + TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification( descriptor, annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace), !typeParameter.hasModifier(JetTokens.ERASED_KEYWORD), @@ -175,7 +175,7 @@ public class DescriptorResolver { WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function descriptor header scope"); innerScope.addLabeledDeclaration(functionDescriptor); - List typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters(), trace); + List typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters(), trace); innerScope.changeLockLevel(WritableScope.LockLevel.BOTH); resolveGenericBounds(function, innerScope, typeParameterDescriptors, trace); @@ -307,8 +307,8 @@ public class DescriptorResolver { } } - public List resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List typeParameters, BindingTrace trace) { - List result = new ArrayList(); + public List resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List typeParameters, BindingTrace trace) { + List result = new ArrayList(); for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) { JetTypeParameter typeParameter = typeParameters.get(i); result.add(resolveTypeParameter(containingDescriptor, extensibleScope, typeParameter, i, trace)); @@ -316,12 +316,12 @@ public class DescriptorResolver { return result; } - private TypeParameterDescriptor resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter, int index, BindingTrace trace) { + private TypeParameterDescriptorImpl resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter, int index, BindingTrace trace) { // JetTypeReference extendsBound = typeParameter.getExtendsBound(); // JetType bound = extendsBound == null // ? JetStandardClasses.getDefaultBound() // : typeResolver.resolveType(extensibleScope, extendsBound); - TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification( + TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification( containingDescriptor, annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace), !typeParameter.hasModifier(JetTokens.ERASED_KEYWORD), @@ -346,14 +346,15 @@ public class DescriptorResolver { isClassObjectConstraint = classObjectConstraint; } } - public void resolveGenericBounds(@NotNull JetTypeParameterListOwner declaration, JetScope scope, List parameters, BindingTrace trace) { + + public void resolveGenericBounds(@NotNull JetTypeParameterListOwner declaration, JetScope scope, List parameters, BindingTrace trace) { List deferredUpperBoundCheckerTasks = Lists.newArrayList(); List typeParameters = declaration.getTypeParameters(); - Map parameterByName = Maps.newHashMap(); + Map parameterByName = Maps.newHashMap(); for (int i = 0; i < typeParameters.size(); i++) { JetTypeParameter jetTypeParameter = typeParameters.get(i); - TypeParameterDescriptor typeParameterDescriptor = parameters.get(i); + TypeParameterDescriptorImpl typeParameterDescriptor = parameters.get(i); parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor); @@ -373,7 +374,7 @@ public class DescriptorResolver { if (referencedName == null) { continue; } - TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName); + TypeParameterDescriptorImpl typeParameterDescriptor = parameterByName.get(referencedName); JetTypeReference boundTypeReference = constraint.getBoundTypeReference(); JetType bound = null; if (boundTypeReference != null) { @@ -405,7 +406,7 @@ public class DescriptorResolver { } } - for (TypeParameterDescriptor parameter : parameters) { + for (TypeParameterDescriptorImpl parameter : parameters) { parameter.addDefaultUpperBound(); parameter.setInitialized(); @@ -551,7 +552,7 @@ public class DescriptorResolver { return variableDescriptor; } - public JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull List typeParameters, + public JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull List typeParameters, @NotNull ReceiverDescriptor receiver, BindingTrace trace) { WritableScopeImpl result = new WritableScopeImpl(outerScope, outerScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace)).setDebugName("Property declaration inner scope"); for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { @@ -583,7 +584,7 @@ public class DescriptorResolver { CallableMemberDescriptor.Kind.DECLARATION ); - List typeParameterDescriptors; + List typeParameterDescriptors; JetScope scopeWithTypeParameters; JetType receiverType = null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 40ba883128e..ce8f0bbea4a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -275,7 +275,7 @@ public class DescriptorUtils { ClassDescriptor clazz = (ClassDescriptor) classifier; return clazz.getKind() == ClassKind.OBJECT || clazz.getKind() == ClassKind.ENUM_ENTRY; } - else if (classifier instanceof TypeParameterDescriptor) { + else if (classifier instanceof TypeParameterDescriptorImpl) { return false; } else { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index 8c7fe2bbe18..2ecf21fd46e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -212,7 +212,7 @@ public class OverridingUtil { if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) { return type; } - else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { + else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) { return ((TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor()).getUpperBoundsAsType(); } else { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index b5d65c3bcef..b0e53273c38 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -395,7 +395,7 @@ public class TypeHierarchyResolver { JetClass jetClass = entry.getKey(); MutableClassDescriptor descriptor = entry.getValue(); descriptorResolver.resolveGenericBounds(jetClass, descriptor.getScopeForSupertypeResolution(), - descriptor.getTypeConstructor().getParameters(), trace); + (List) descriptor.getTypeConstructor().getParameters(), trace); descriptorResolver.resolveSupertypes(jetClass, descriptor, trace); } for (Map.Entry entry : context.getObjects().entrySet()) { @@ -528,7 +528,7 @@ public class TypeHierarchyResolver { if (projections.size() > 1) { TypeConstructor typeConstructor = entry.getKey(); DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor(); - assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor; + assert declarationDescriptor instanceof TypeParameterDescriptorImpl : declarationDescriptor; TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; // Immediate arguments of supertypes cannot be projected diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index ab54ab52fe4..a189b882c66 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -95,7 +95,7 @@ public class TypeResolver { return; } - if (classifierDescriptor instanceof TypeParameterDescriptor) { + if (classifierDescriptor instanceof TypeParameterDescriptorImpl) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor; trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java index 022b909c68f..65a2ee84422 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java @@ -21,6 +21,7 @@ import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure; @@ -88,7 +89,7 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem { @NotNull private TypeValue getTypeValueFor(@NotNull JetType type) { DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); - if (declarationDescriptor instanceof TypeParameterDescriptor) { + if (declarationDescriptor instanceof TypeParameterDescriptorImpl) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; // Checking that this is not a T?, but exactly T if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) { @@ -488,7 +489,7 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem { @Override public TypeProjection get(TypeConstructor key) { DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); - if (declarationDescriptor instanceof TypeParameterDescriptor) { + if (declarationDescriptor instanceof TypeParameterDescriptorImpl) { TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; if (!unknownTypes.containsKey(descriptor)) return null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java index eada1237fb8..132f75ede6e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java @@ -20,6 +20,7 @@ import com.google.common.collect.Maps; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl; import java.util.List; import java.util.Map; @@ -58,7 +59,7 @@ public class DescriptorSubstitutor { }); for (TypeParameterDescriptor descriptor : typeParameters) { - TypeParameterDescriptor substituted = TypeParameterDescriptor.createForFurtherModification( + TypeParameterDescriptorImpl substituted = TypeParameterDescriptorImpl.createForFurtherModification( newContainingDeclaration, descriptor.getAnnotations(), descriptor.isReified(), diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java index e3fcb857a03..5f24e97621f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -170,7 +170,7 @@ public class ErrorUtils { function.initialize( null, ReceiverDescriptor.NO_RECEIVER, - Collections.emptyList(), // TODO + Collections.emptyList(), // TODO Collections.emptyList(), // TODO createErrorType(""), Modality.OPEN, @@ -223,7 +223,7 @@ public class ErrorUtils { } private static JetType createErrorTypeWithCustomDebugName(JetScope memberScope, String debugName) { - return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.emptyList(), false, debugName, Collections.emptyList(), Collections.singleton(JetStandardClasses.getAnyType())), memberScope); + return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.emptyList(), false, debugName, Collections.emptyList(), Collections.singleton(JetStandardClasses.getAnyType())), memberScope); } public static JetType createWrongVarianceErrorType(TypeProjection value) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java index 6fe27a072e6..2c62f5d51fe 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/SubstitutionUtils.java @@ -21,6 +21,7 @@ import com.google.common.collect.Multimap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.util.CommonSuppliers; @@ -111,7 +112,7 @@ public class SubstitutionUtils { } public static boolean hasUnsubstitutedTypeParameters(JetType type) { - if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { + if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) { return true; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java index 1d1eceb5ef8..16216bc779c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java @@ -45,7 +45,7 @@ public class TypeConstructorImpl extends AnnotatedImpl implements TypeConstructo @NotNull List annotations, boolean sealed, @NotNull String debugName, - @NotNull List parameters, + @NotNull List parameters, @NotNull Collection supertypes) { super(annotations); this.classifierDescriptor = classifierDescriptor; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index e3ae251dbef..7bf184d015f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -22,10 +22,7 @@ import com.google.common.collect.Sets; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; @@ -222,7 +219,7 @@ public class TypeUtils { private static void processAllTypeParameters(JetType type, Variance howThiTypeIsUsed, Processor result) { ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); - if (descriptor instanceof TypeParameterDescriptor) { + if (descriptor instanceof TypeParameterDescriptorImpl) { result.process(new TypeParameterUsage((TypeParameterDescriptor)descriptor, howThiTypeIsUsed)); } for (TypeProjection projection : type.getArguments()) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 8a4ea7ea3c0..6f2c5e6f2a3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -149,7 +149,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { } functionDescriptor.initialize(effectiveReceiverType, NO_RECEIVER, - Collections.emptyList(), + Collections.emptyList(), valueParameterDescriptors, /*unsubstitutedReturnType = */ null, Modality.FINAL, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardClasses.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardClasses.java index dbec3286f6f..ee62cc2f842 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardClasses.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardClasses.java @@ -157,13 +157,13 @@ public class JetStandardClasses { Name.identifier("Tuple" + i)); WritableScopeImpl writableScope = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, RedeclarationHandler.THROW_EXCEPTION); for (int j = 0; j < i; j++) { - TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createWithDefaultBound( + TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptorImpl.createWithDefaultBound( classDescriptor, Collections.emptyList(), true, Variance.OUT_VARIANCE, Name.identifier("T" + (j + 1)), j); parameters.add(typeParameterDescriptor); PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor, Collections.emptyList(), Modality.FINAL, Visibilities.PUBLIC, false, false, Name.identifier("_" + (j + 1)), CallableMemberDescriptor.Kind.DECLARATION); - propertyDescriptor.setType(typeParameterDescriptor.getDefaultType(), Collections.emptyList(), classDescriptor.getImplicitReceiver(), ReceiverDescriptor.NO_RECEIVER); + propertyDescriptor.setType(typeParameterDescriptor.getDefaultType(), Collections.emptyList(), classDescriptor.getImplicitReceiver(), ReceiverDescriptor.NO_RECEIVER); PropertyGetterDescriptor getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.FINAL, Visibilities.PUBLIC, false, true, CallableMemberDescriptor.Kind.DECLARATION); getterDescriptor.initialize(typeParameterDescriptor.getDefaultType()); propertyDescriptor.initialize(getterDescriptor, null); @@ -215,7 +215,7 @@ public class JetStandardClasses { SimpleFunctionDescriptorImpl invokeWithReceiver = new SimpleFunctionDescriptorImpl(receiverFunction, Collections.emptyList(), Name.identifier("invoke"), CallableMemberDescriptor.Kind.DECLARATION); WritableScope scopeForInvokeWithReceiver = createScopeForInvokeFunction(receiverFunction, invokeWithReceiver); List parameters = createTypeParameters(i, receiverFunction); - parameters.add(0, TypeParameterDescriptor.createWithDefaultBound( + parameters.add(0, TypeParameterDescriptorImpl.createWithDefaultBound( receiverFunction, Collections.emptyList(), true, Variance.IN_VARIANCE, Name.identifier("T"), 0)); @@ -238,12 +238,12 @@ public class JetStandardClasses { private static List createTypeParameters(int parameterCount, ClassDescriptorImpl function) { List parameters = new ArrayList(); for (int j = 1; j <= parameterCount; j++) { - parameters.add(TypeParameterDescriptor.createWithDefaultBound( + parameters.add(TypeParameterDescriptorImpl.createWithDefaultBound( function, Collections.emptyList(), true, Variance.IN_VARIANCE, Name.identifier("P" + j), j)); } - parameters.add(TypeParameterDescriptor.createWithDefaultBound( + parameters.add(TypeParameterDescriptorImpl.createWithDefaultBound( function, Collections.emptyList(), true, Variance.OUT_VARIANCE, Name.identifier("R"), parameterCount + 1)); diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index ec2517a0856..d38cba2cb79 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -146,7 +146,7 @@ public class DescriptorRenderer implements Renderer { Object typeNameObject; - if (cd == null || cd instanceof TypeParameterDescriptor) { + if (cd == null || cd instanceof TypeParameterDescriptorImpl) { typeNameObject = type.getConstructor(); } else { diff --git a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 671abc34e72..e27e075ff51 100644 --- a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -698,7 +698,7 @@ public class JetTypeCheckerTest extends JetLiteFixture { parameterScope.changeLockLevel(WritableScope.LockLevel.BOTH); // This call has side-effects on the parameterScope (fills it in) - List typeParameters + List typeParameters = descriptorResolver.resolveTypeParameters(classDescriptor, parameterScope, classElement.getTypeParameters(), JetTestUtils.DUMMY_TRACE); descriptorResolver.resolveGenericBounds(classElement, parameterScope, typeParameters, JetTestUtils.DUMMY_TRACE); diff --git a/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java b/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java index 862eea63b29..e2a8270280f 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java @@ -110,7 +110,7 @@ public final class JetDescriptorIconProvider { return ((PropertyDescriptor)descriptor).isVar() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL; } - if (descriptor instanceof TypeParameterDescriptor) { + if (descriptor instanceof TypeParameterDescriptorImpl) { return PlatformIcons.CLASS_ICON; } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index 0298a6a83b9..a4321a5cb06 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -183,7 +183,7 @@ public class JetCompletionContributor extends CompletionContributor { DeclarationDescriptor descriptor = ((JetLookupObject)object).getDescriptor(); return (descriptor instanceof ClassDescriptor) || (descriptor instanceof NamespaceDescriptor) || - (descriptor instanceof TypeParameterDescriptor); + (descriptor instanceof TypeParameterDescriptorImpl); } }