private boolean isInDistanceInternal( int distance, NetworkNode from, NetworkNode to, TwoNetworkNodes cachePairKey) { if (from.equals(to)) return true; if (distance == 0) return false; if (SimpleNetwork.areNodesConnecting(from, to)) return true; // Breadth-first search of the network Set<NetworkNode> visitedNodes = Sets.newHashSet(); visitedNodes.add(from); Set<NetworkNode> networkingNodesToTest = Sets.newHashSet(); listConnectedNotVisitedNetworkingNodes(visitedNodes, from, networkingNodesToTest); int distanceSearched = 1; while (distanceSearched < distance) { distanceSearched++; for (NetworkNode nodeToTest : networkingNodesToTest) { if (SimpleNetwork.areNodesConnecting(nodeToTest, to)) { distanceCache.put(cachePairKey, distanceSearched); return true; } visitedNodes.add(nodeToTest); } Set<NetworkNode> nextNetworkingNodesToTest = Sets.newHashSet(); for (NetworkNode nodeToTest : networkingNodesToTest) listConnectedNotVisitedNetworkingNodes(visitedNodes, nodeToTest, nextNetworkingNodesToTest); networkingNodesToTest = nextNetworkingNodesToTest; } return false; }
/** * expand super types after scanning, for super types that were not scanned. this is helpful in * finding the transitive closure without scanning all 3rd party dependencies. it uses {@link * ReflectionUtils#getSuperTypes(Class)}. * * <p>for example, for classes A,B,C where A supertype of B, B supertype of C: * * <ul> * <li>if scanning C resulted in B (B->C in store), but A was not scanned (although A supertype * of B) - then getSubTypes(A) will not return C * <li>if expanding supertypes, B will be expanded with A (A->B in store) - then getSubTypes(A) * will return C * </ul> */ public void expandSuperTypes() { if (store.keySet().contains(index(SubTypesScanner.class))) { Multimap<String, String> mmap = store.get(index(SubTypesScanner.class)); Sets.SetView<String> keys = Sets.difference(mmap.keySet(), Sets.newHashSet(mmap.values())); Multimap<String, String> expand = HashMultimap.create(); for (String key : keys) { expandSupertypes(expand, key, forName(key)); } mmap.putAll(expand); } }
/** * get types annotated with a given annotation, both classes and annotations, including annotation * member values matching * * <p>{@link Inherited} is honored according to given honorInherited * * <p>depends on TypeAnnotationsScanner configured */ public Set<Class<?>> getTypesAnnotatedWith(final Annotation annotation, boolean honorInherited) { Iterable<String> annotated = store.get(index(TypeAnnotationsScanner.class), annotation.annotationType().getName()); Iterable<Class<?>> filter = filter(forNames(annotated, loaders()), withAnnotation(annotation)); Iterable<String> classes = getAllAnnotated( names(filter), annotation.annotationType().isAnnotationPresent(Inherited.class), honorInherited); return Sets.newHashSet( concat(filter, forNames(filter(classes, not(in(Sets.newHashSet(annotated)))), loaders()))); }
private Variance calculateArgumentProjectionKindFromSuper( @NotNull TypeProjection argument, @NotNull List<TypeProjectionAndVariance> projectionsFromSuper) { Set<Variance> projectionKindsInSuper = Sets.newLinkedHashSet(); for (TypeProjectionAndVariance projectionAndVariance : projectionsFromSuper) { projectionKindsInSuper.add(projectionAndVariance.typeProjection.getProjectionKind()); } Variance defaultProjectionKind = argument.getProjectionKind(); if (projectionKindsInSuper.size() == 0) { return defaultProjectionKind; } else if (projectionKindsInSuper.size() == 1) { Variance projectionKindInSuper = projectionKindsInSuper.iterator().next(); if (defaultProjectionKind == INVARIANT || defaultProjectionKind == projectionKindInSuper) { return projectionKindInSuper; } else { reportError( "Incompatible projection kinds in type arguments of super methods' return types: " + projectionsFromSuper + ", defined in current: " + argument); return defaultProjectionKind; } } else { reportError( "Incompatible projection kinds in type arguments of super methods' return types: " + projectionsFromSuper); return defaultProjectionKind; } }
@NonNull public IAndroidTarget[] getMissingTargets() { synchronized (mLocalPackages) { if (mCachedMissingTargets == null) { Map<MissingTarget, MissingTarget> result = Maps.newHashMap(); Set<ISystemImage> seen = Sets.newHashSet(); for (IAndroidTarget target : getTargets()) { Collections.addAll(seen, target.getSystemImages()); } for (LocalPkgInfo local : getPkgsInfos(PkgType.PKG_ADDON_SYS_IMAGE)) { LocalAddonSysImgPkgInfo info = (LocalAddonSysImgPkgInfo) local; ISystemImage image = info.getSystemImage(); if (!seen.contains(image)) { addOrphanedSystemImage(image, info.getDesc(), result); } } for (LocalPkgInfo local : getPkgsInfos(PkgType.PKG_SYS_IMAGE)) { LocalSysImgPkgInfo info = (LocalSysImgPkgInfo) local; ISystemImage image = info.getSystemImage(); if (!seen.contains(image)) { addOrphanedSystemImage(image, info.getDesc(), result); } } mCachedMissingTargets = result.keySet(); } return mCachedMissingTargets.toArray(new IAndroidTarget[mCachedMissingTargets.size()]); } }
/** * get all fields annotated with a given annotation * * <p>depends on FieldAnnotationsScanner configured */ public Set<Field> getFieldsAnnotatedWith(final Class<? extends Annotation> annotation) { final Set<Field> result = Sets.newHashSet(); for (String annotated : store.get(index(FieldAnnotationsScanner.class), annotation.getName())) { result.add(getFieldFromString(annotated, loaders())); } return result; }
public static TileEntity getTileEntity(IBlockAccess blockaccess, int x, int y, int z) { HashSet<ChunkCoordinates> visited = Sets.newHashSet(); Block block = blockaccess.getBlock(x, y, z); while (block != NailedBlocks.portalController) { if (isValidLinkPortalBlock(block) == 0) { return null; } ChunkCoordinates pos = new ChunkCoordinates(x, y, z); if (!visited.add(pos)) { return null; } int meta = blockaccess.getBlockMetadata(x, y, z); if (meta == 0) { return null; } if (meta == 1) { y--; } else if (meta == 2) { y++; } else if (meta == 3) { z--; } else if (meta == 4) { z++; } else if (meta == 5) { x--; } else if (meta == 6) { x++; } else { return null; } block = blockaccess.getBlock(x, y, z); } return blockaccess.getTileEntity(x, y, z); }
/** * Assigns sequential identifiers to the provided <code>clusters</code> (and their sub-clusters). * If a cluster already has an identifier, the identifier will not be changed. * * @param clusters Clusters to assign identifiers to. * @throws IllegalArgumentException if the provided clusters contain non-unique identifiers */ public static void assignClusterIds(Collection<Cluster> clusters) { final ArrayList<Cluster> flattened = Lists.newArrayListWithExpectedSize(clusters.size()); flatten(flattened, clusters); synchronized (clusters) { final HashSet<Integer> ids = Sets.newHashSet(); // First, find the start value for the id and check uniqueness of the ids // already provided. int maxId = Integer.MIN_VALUE; for (final Cluster cluster : flattened) { if (cluster.id != null) { if (!ids.add(cluster.id)) { throw new IllegalArgumentException("Non-unique cluster id found: " + cluster.id); } maxId = Math.max(maxId, cluster.id); } } // We'd rather start with 0 maxId = Math.max(maxId, -1); // Assign missing ids for (final Cluster c : flattened) { if (c.id == null) { c.id = ++maxId; } } } }
// Loop through all changed classes, adding their parents (and their // parents) // to another set of changed classes public Set<JavaClass> findChangedParents(Set<JavaClass> classes) { Set<JavaClass> changedParents = Sets.newHashSet(classes); for (JavaClass jclass : classes) { findParents(jclass, changedParents); } return changedParents; }
/** * Builds an "Other Topics" cluster that groups those documents from <code>allDocument</code> that * were not referenced in any cluster in <code>clusters</code>. * * @param allDocuments all documents to check against * @param clusters list of clusters with assigned documents * @param label label for the "Other Topics" group * @return the "Other Topics" cluster */ public static Cluster buildOtherTopics( List<Document> allDocuments, List<Cluster> clusters, String label) { final Set<Document> unclusteredDocuments = Sets.newLinkedHashSet(allDocuments); final Set<Document> assignedDocuments = Sets.newHashSet(); for (Cluster cluster : clusters) { collectAllDocuments(cluster, assignedDocuments); } unclusteredDocuments.removeAll(assignedDocuments); final Cluster otherTopics = new Cluster(label); otherTopics.addDocuments(unclusteredDocuments); otherTopics.setOtherTopics(true); return otherTopics; }
/** * get types annotated with a given annotation, both classes and annotations * * <p>{@link Inherited} is honored according to given honorInherited. * * <p>when honoring @Inherited, meta-annotation should only effect annotated super classes and * it's sub types * * <p>when not honoring @Inherited, meta annotation effects all subtypes, including annotations * interfaces and classes * * <p><i>Note that this (@Inherited) meta-annotation type has no effect if the annotated type is * used for anything other then a class. Also, this meta-annotation causes annotations to be * inherited only from superclasses; annotations on implemented interfaces have no effect.</i> * * <p>depends on TypeAnnotationsScanner and SubTypesScanner configured */ public Set<Class<?>> getTypesAnnotatedWith( final Class<? extends Annotation> annotation, boolean honorInherited) { Iterable<String> annotated = store.get(index(TypeAnnotationsScanner.class), annotation.getName()); Iterable<String> classes = getAllAnnotated(annotated, annotation.isAnnotationPresent(Inherited.class), honorInherited); return Sets.newHashSet(concat(forNames(annotated, loaders()), forNames(classes, loaders()))); }
/** * get all types scanned. this is effectively similar to getting all subtypes of Object. * * <p>depends on SubTypesScanner configured with {@code SubTypesScanner(false)}, otherwise {@code * ReflectionsException} is thrown * * <p><i>note using this might be a bad practice. it is better to get types matching some * criteria, such as {@link #getSubTypesOf(Class)} or {@link #getTypesAnnotatedWith(Class)}</i> * * @return Set of String, and not of Class, in order to avoid definition of all types in PermGen */ public Set<String> getAllTypes() { Set<String> allTypes = Sets.newHashSet(store.getAll(index(SubTypesScanner.class), Object.class.getName())); if (allTypes.isEmpty()) { throw new ReflectionsException( "Couldn't find subtypes of Object. " + "Make sure SubTypesScanner initialized to include Object class - new SubTypesScanner(false)"); } return allTypes; }
/** * @param gcBefore * @return */ private List<SSTableReader> getNextBackgroundSSTables(final int gcBefore) { if (!isEnabled() || cfs.getSSTables().isEmpty()) return Collections.emptyList(); Set<SSTableReader> uncompacting = Sets.intersection(sstables, cfs.getUncompactingSSTables()); // Find fully expired SSTables. Those will be included no matter what. Set<SSTableReader> expired = CompactionController.getFullyExpiredSSTables( cfs, uncompacting, cfs.getOverlappingSSTables(uncompacting), gcBefore); Set<SSTableReader> candidates = Sets.newHashSet(filterSuspectSSTables(uncompacting)); List<SSTableReader> compactionCandidates = new ArrayList<>(getNextNonExpiredSSTables(Sets.difference(candidates, expired), gcBefore)); if (!expired.isEmpty()) { logger.debug("Including expired sstables: {}", expired); compactionCandidates.addAll(expired); } return compactionCandidates; }
Set<Object> getPartitions(List<Document> documents) { final HashSet<Object> partitions = Sets.newHashSet(); for (Document document : documents) { final Collection<Object> documentPartitions = document.<Collection<Object>>getField(partitionIdFieldName); if (documentPartitions != null) { partitions.addAll(documentPartitions); } } return partitions; }
private void markDeadInstructions() { Set<Instruction> instructionSet = Sets.newHashSet(instructions); for (Instruction instruction : mutableInstructionList) { if (!instructionSet.contains(instruction)) { ((InstructionImpl) instruction).setMarkedAsDead(true); for (Instruction nextInstruction : instruction.getNextInstructions()) { nextInstruction.getPreviousInstructions().remove(instruction); } } } }
@Override public int getDistance(NetworkNode from, NetworkNode to) { TwoNetworkNodes nodePair = new TwoNetworkNodes(from, to); final Integer cachedDistance = distanceCache.get(nodePair); if (cachedDistance != null) return cachedDistance; if ((!hasNetworkingNode(from) && !hasLeafNode(from)) || (!hasNetworkingNode(to) && !hasLeafNode(to))) throw new IllegalArgumentException("Cannot test nodes not in network"); if (from.equals(to)) return 0; if (SimpleNetwork.areNodesConnecting(from, to)) return 1; // Breadth-first search of the network Set<NetworkNode> visitedNodes = Sets.newHashSet(); visitedNodes.add(from); Set<NetworkNode> networkingNodesToTest = Sets.newHashSet(); listConnectedNotVisitedNetworkingNodes(visitedNodes, from, networkingNodesToTest); int distanceSearched = 1; while (networkingNodesToTest.size() > 0) { distanceSearched++; for (NetworkNode nodeToTest : networkingNodesToTest) { if (SimpleNetwork.areNodesConnecting(nodeToTest, to)) { distanceCache.put(new TwoNetworkNodes(from, to), distanceSearched); return distanceSearched; } visitedNodes.add(nodeToTest); } Set<NetworkNode> nextNetworkingNodesToTest = Sets.newHashSet(); for (NetworkNode nodeToTest : networkingNodesToTest) listConnectedNotVisitedNetworkingNodes(visitedNodes, nodeToTest, nextNetworkingNodesToTest); networkingNodesToTest = nextNetworkingNodesToTest; } return -1; }
@NotNull private static Set<LocalFunctionDeclarationInstruction> getLocalDeclarations( @NotNull Pseudocode pseudocode) { Set<LocalFunctionDeclarationInstruction> localDeclarations = Sets.newLinkedHashSet(); for (Instruction instruction : ((PseudocodeImpl) pseudocode).mutableInstructionList) { if (instruction instanceof LocalFunctionDeclarationInstruction) { localDeclarations.add((LocalFunctionDeclarationInstruction) instruction); localDeclarations.addAll( getLocalDeclarations(((LocalFunctionDeclarationInstruction) instruction).getBody())); } } return localDeclarations; }
private Set<Instruction> collectReachableInstructions() { Set<Instruction> visited = Sets.newHashSet(); PseudocodeTraverserKt.traverseFollowingInstructions( getEnterInstruction(), visited, FORWARD, null); if (!visited.contains(getExitInstruction())) { visited.add(getExitInstruction()); } if (!visited.contains(errorInstruction)) { visited.add(errorInstruction); } if (!visited.contains(getSinkInstruction())) { visited.add(getSinkInstruction()); } return visited; }
/** * Returns all the fields that match the given pattern. If the pattern is prefixed with a type * then the fields will be returned with a type prefix. */ public Set<String> simpleMatchToIndexNames(String pattern) { if (!Regex.isSimpleMatchPattern(pattern)) { return ImmutableSet.of(pattern); } int dotIndex = pattern.indexOf('.'); if (dotIndex != -1) { String possibleType = pattern.substring(0, dotIndex); DocumentMapper possibleDocMapper = mappers.get(possibleType); if (possibleDocMapper != null) { Set<String> typedFields = Sets.newHashSet(); for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) { typedFields.add(possibleType + "." + indexName); } return typedFields; } } return fieldMappers.simpleMatchToIndexNames(pattern); }
@NotNull @Override public List<Instruction> getReversedInstructions() { LinkedHashSet<Instruction> traversedInstructions = Sets.newLinkedHashSet(); PseudocodeTraverserKt.traverseFollowingInstructions( sinkInstruction, traversedInstructions, BACKWARD, null); if (traversedInstructions.size() < instructions.size()) { List<Instruction> simplyReversedInstructions = Lists.newArrayList(instructions); Collections.reverse(simplyReversedInstructions); for (Instruction instruction : simplyReversedInstructions) { if (!traversedInstructions.contains(instruction)) { PseudocodeTraverserKt.traverseFollowingInstructions( instruction, traversedInstructions, BACKWARD, null); } } } return Lists.newArrayList(traversedInstructions); }
private void checkRedeclarationsInPackages(@NotNull TopDownAnalysisContext c) { for (MutablePackageFragmentDescriptor packageFragment : Sets.newHashSet(c.getPackageFragments().values())) { PackageViewDescriptor packageView = packageFragment.getContainingDeclaration().getPackage(packageFragment.getFqName()); JetScope packageViewScope = packageView.getMemberScope(); Multimap<Name, DeclarationDescriptor> simpleNameDescriptors = packageFragment.getMemberScope().getDeclaredDescriptorsAccessibleBySimpleName(); for (Name name : simpleNameDescriptors.keySet()) { // Keep only properties with no receiver Collection<DeclarationDescriptor> descriptors = Collections2.filter( simpleNameDescriptors.get(name), new Predicate<DeclarationDescriptor>() { @Override public boolean apply(@Nullable DeclarationDescriptor descriptor) { if (descriptor instanceof PropertyDescriptor) { PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; return propertyDescriptor.getReceiverParameter() == null; } return true; } }); ContainerUtil.addIfNotNull(descriptors, packageViewScope.getPackage(name)); if (descriptors.size() > 1) { for (DeclarationDescriptor declarationDescriptor : descriptors) { for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) { assert declaration != null : "Null declaration for descriptor: " + declarationDescriptor + " " + (declarationDescriptor != null ? DescriptorRenderer.FQ_NAMES_IN_TYPES.render(declarationDescriptor) : ""); trace.report( REDECLARATION.on(declaration, declarationDescriptor.getName().asString())); } } } } } }
/** * Returns all the fields that match the given pattern, with an optional narrowing based on a list * of types. */ public Set<String> simpleMatchToIndexNames(String pattern, @Nullable String[] types) { if (types == null || types.length == 0) { return simpleMatchToIndexNames(pattern); } if (types.length == 1 && types[0].equals("_all")) { return simpleMatchToIndexNames(pattern); } if (!Regex.isSimpleMatchPattern(pattern)) { return ImmutableSet.of(pattern); } Set<String> fields = Sets.newHashSet(); for (String type : types) { DocumentMapper possibleDocMapper = mappers.get(type); if (possibleDocMapper != null) { for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) { fields.add(indexName); } } } return fields; }
private void writeGetters(ClassVisitor visitor, Type generatedType, ModelProperty<?> property) { Class<?> propertyClass = property.getType().getConcreteClass(); Type propertyType = Type.getType(propertyClass); Set<String> processedNames = Sets.newHashSet(); for (WeaklyTypeReferencingMethod<?, ?> weakGetter : property.getGetters()) { Method getter = weakGetter.getMethod(); if (!processedNames.add(getter.getName())) { continue; } MethodVisitor methodVisitor = declareMethod( visitor, getter.getName(), Type.getMethodDescriptor(propertyType), AsmClassGeneratorUtils.signature(getter)); putStateFieldValueOnStack(methodVisitor, generatedType); putConstantOnStack(methodVisitor, property.getName()); invokeStateGetMethod(methodVisitor); castFirstStackElement(methodVisitor, propertyClass); finishVisitingMethod(methodVisitor, returnCode(propertyType)); } }
private void reportRedeclarations(@NotNull Multimap<Name, DeclarationDescriptor> descriptorMap) { Set<Pair<PsiElement, Name>> redeclarations = Sets.newHashSet(); for (Name name : descriptorMap.keySet()) { Collection<DeclarationDescriptor> descriptors = descriptorMap.get(name); if (descriptors.size() > 1) { // We mustn't compare PropertyDescriptor with PropertyDescriptor because we do this at // OverloadResolver for (DeclarationDescriptor descriptor : descriptors) { if (descriptor instanceof ClassDescriptor) { for (DeclarationDescriptor descriptor2 : descriptors) { if (descriptor == descriptor2) { continue; } redeclarations.add( Pair.create( BindingContextUtils.classDescriptorToDeclaration( trace.getBindingContext(), (ClassDescriptor) descriptor), descriptor.getName())); if (descriptor2 instanceof PropertyDescriptor) { redeclarations.add( Pair.create( BindingContextUtils.descriptorToDeclaration( trace.getBindingContext(), descriptor2), descriptor2.getName())); } } } } } } for (Pair<PsiElement, Name> redeclaration : redeclarations) { trace.report( REDECLARATION.on(redeclaration.getFirst(), redeclaration.getSecond().asString())); } }
/** * gets all sub types in hierarchy of a given type * * <p>depends on SubTypesScanner configured */ public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) { return Sets.newHashSet( ReflectionUtils.<T>forNames( store.getAll(index(SubTypesScanner.class), Arrays.asList(type.getName())), loaders())); }
/** * get resources relative paths where simple name (key) matches given namePredicate * * <p>depends on ResourcesScanner configured */ public Set<String> getResources(final Predicate<String> namePredicate) { Iterable<String> resources = Iterables.filter(store.get(index(ResourcesScanner.class)).keySet(), namePredicate); return Sets.newHashSet(store.get(index(ResourcesScanner.class), resources)); }
@Override public Iterator<TitanElement> getNew(final StandardElementQuery query) { Preconditions.checkArgument( query.getType() == StandardElementQuery.Type.VERTEX || query.getType() == StandardElementQuery.Type.EDGE); if (query.getType() == StandardElementQuery.Type.VERTEX && hasModifications()) { // Collect all keys from the query - ASSUMPTION: query is an AND of KeyAtom final Set<TitanKey> keys = Sets.newHashSet(); KeyAtom<TitanKey> standardIndexKey = null; for (KeyCondition<TitanKey> cond : query.getCondition().getChildren()) { KeyAtom<TitanKey> atom = (KeyAtom<TitanKey>) cond; if (atom.getRelation() == Cmp.EQUAL && isVertexIndexProperty(atom.getKey())) standardIndexKey = atom; keys.add(atom.getKey()); } Iterator<TitanVertex> vertices; if (standardIndexKey == null) { Set<TitanVertex> vertexSet = Sets.newHashSet(); for (TitanRelation r : addedRelations.getView( new Predicate<InternalRelation>() { @Override public boolean apply(@Nullable InternalRelation relation) { return keys.contains(relation.getType()); } })) { vertexSet.add(((TitanProperty) r).getVertex()); } for (TitanRelation r : deletedRelations.values()) { if (keys.contains(r.getType())) { TitanVertex v = ((TitanProperty) r).getVertex(); if (!v.isRemoved()) vertexSet.add(v); } } vertices = vertexSet.iterator(); } else { vertices = Iterators.transform( newVertexIndexEntries .get(standardIndexKey.getCondition(), standardIndexKey.getKey()) .iterator(), new Function<TitanProperty, TitanVertex>() { @Nullable @Override public TitanVertex apply(@Nullable TitanProperty o) { return o.getVertex(); } }); } return (Iterator) Iterators.filter( vertices, new Predicate<TitanVertex>() { @Override public boolean apply(@Nullable TitanVertex vertex) { return query.matches(vertex); } }); } else if (query.getType() == StandardElementQuery.Type.EDGE && !addedRelations.isEmpty()) { return (Iterator) addedRelations .getView( new Predicate<InternalRelation>() { @Override public boolean apply(@Nullable InternalRelation relation) { return (relation instanceof TitanEdge) && !relation.isHidden() && query.matches(relation); } }) .iterator(); } else throw new IllegalArgumentException("Unexpected type: " + query.getType()); }
public class PseudocodeImpl implements Pseudocode { public class PseudocodeLabel implements Label { private final String name; private final String comment; private Integer targetInstructionIndex; private PseudocodeLabel(@NotNull String name, @Nullable String comment) { this.name = name; this.comment = comment; } @NotNull @Override public String getName() { return name; } @Override public String toString() { return comment == null ? name : (name + " [" + comment + "]"); } public Integer getTargetInstructionIndex() { return targetInstructionIndex; } public void setTargetInstructionIndex(int targetInstructionIndex) { this.targetInstructionIndex = targetInstructionIndex; } @Nullable private List<Instruction> resolve() { assert targetInstructionIndex != null; return mutableInstructionList.subList( getTargetInstructionIndex(), mutableInstructionList.size()); } public Instruction resolveToInstruction() { assert targetInstructionIndex != null; return mutableInstructionList.get(targetInstructionIndex); } public PseudocodeLabel copy(int newLabelIndex) { return new PseudocodeLabel("L" + newLabelIndex, "copy of " + name + ", " + comment); } public PseudocodeImpl getPseudocode() { return PseudocodeImpl.this; } } private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>(); private final List<Instruction> instructions = new ArrayList<Instruction>(); private final BidirectionalMap<KtElement, PseudoValue> elementsToValues = new BidirectionalMap<KtElement, PseudoValue>(); private final Map<PseudoValue, List<Instruction>> valueUsages = Maps.newHashMap(); private final Map<PseudoValue, Set<PseudoValue>> mergedValues = Maps.newHashMap(); private final Set<Instruction> sideEffectFree = Sets.newHashSet(); private Pseudocode parent = null; private Set<LocalFunctionDeclarationInstruction> localDeclarations = null; // todo getters private final Map<KtElement, Instruction> representativeInstructions = new HashMap<KtElement, Instruction>(); private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>(); private final KtElement correspondingElement; private SubroutineExitInstruction exitInstruction; private SubroutineSinkInstruction sinkInstruction; private SubroutineExitInstruction errorInstruction; private boolean postPrecessed = false; public PseudocodeImpl(KtElement correspondingElement) { this.correspondingElement = correspondingElement; } @NotNull @Override public KtElement getCorrespondingElement() { return correspondingElement; } @NotNull @Override public Set<LocalFunctionDeclarationInstruction> getLocalDeclarations() { if (localDeclarations == null) { localDeclarations = getLocalDeclarations(this); } return localDeclarations; } @NotNull private static Set<LocalFunctionDeclarationInstruction> getLocalDeclarations( @NotNull Pseudocode pseudocode) { Set<LocalFunctionDeclarationInstruction> localDeclarations = Sets.newLinkedHashSet(); for (Instruction instruction : ((PseudocodeImpl) pseudocode).mutableInstructionList) { if (instruction instanceof LocalFunctionDeclarationInstruction) { localDeclarations.add((LocalFunctionDeclarationInstruction) instruction); localDeclarations.addAll( getLocalDeclarations(((LocalFunctionDeclarationInstruction) instruction).getBody())); } } return localDeclarations; } @Override @Nullable public Pseudocode getParent() { return parent; } private void setParent(Pseudocode parent) { this.parent = parent; } @NotNull public Pseudocode getRootPseudocode() { Pseudocode parent = getParent(); while (parent != null) { if (parent.getParent() == null) return parent; parent = parent.getParent(); } return this; } /*package*/ PseudocodeLabel createLabel(@NotNull String name, @Nullable String comment) { PseudocodeLabel label = new PseudocodeLabel(name, comment); labels.add(label); return label; } @Override @NotNull public List<Instruction> getInstructions() { return instructions; } @NotNull @Override public List<Instruction> getReversedInstructions() { LinkedHashSet<Instruction> traversedInstructions = Sets.newLinkedHashSet(); PseudocodeTraverserKt.traverseFollowingInstructions( sinkInstruction, traversedInstructions, BACKWARD, null); if (traversedInstructions.size() < instructions.size()) { List<Instruction> simplyReversedInstructions = Lists.newArrayList(instructions); Collections.reverse(simplyReversedInstructions); for (Instruction instruction : simplyReversedInstructions) { if (!traversedInstructions.contains(instruction)) { PseudocodeTraverserKt.traverseFollowingInstructions( instruction, traversedInstructions, BACKWARD, null); } } } return Lists.newArrayList(traversedInstructions); } @Override @NotNull public List<Instruction> getInstructionsIncludingDeadCode() { return mutableInstructionList; } // for tests only @NotNull public List<PseudocodeLabel> getLabels() { return labels; } /*package*/ void addExitInstruction(SubroutineExitInstruction exitInstruction) { addInstruction(exitInstruction); assert this.exitInstruction == null; this.exitInstruction = exitInstruction; } /*package*/ void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) { addInstruction(sinkInstruction); assert this.sinkInstruction == null; this.sinkInstruction = sinkInstruction; } /*package*/ void addErrorInstruction(SubroutineExitInstruction errorInstruction) { addInstruction(errorInstruction); assert this.errorInstruction == null; this.errorInstruction = errorInstruction; } /*package*/ void addInstruction(Instruction instruction) { mutableInstructionList.add(instruction); instruction.setOwner(this); if (instruction instanceof KtElementInstruction) { KtElementInstruction elementInstruction = (KtElementInstruction) instruction; representativeInstructions.put(elementInstruction.getElement(), instruction); } if (instruction instanceof MergeInstruction) { addMergedValues((MergeInstruction) instruction); } for (PseudoValue inputValue : instruction.getInputValues()) { addValueUsage(inputValue, instruction); for (PseudoValue mergedValue : getMergedValues(inputValue)) { addValueUsage(mergedValue, instruction); } } if (PseudocodeUtilsKt.calcSideEffectFree(instruction)) { sideEffectFree.add(instruction); } } @Override @NotNull public SubroutineExitInstruction getExitInstruction() { return exitInstruction; } @Override @NotNull public SubroutineSinkInstruction getSinkInstruction() { return sinkInstruction; } @Override @NotNull public SubroutineEnterInstruction getEnterInstruction() { return (SubroutineEnterInstruction) mutableInstructionList.get(0); } @Nullable @Override public PseudoValue getElementValue(@Nullable KtElement element) { return elementsToValues.get(element); } @NotNull @Override public List<? extends KtElement> getValueElements(@Nullable PseudoValue value) { List<? extends KtElement> result = elementsToValues.getKeysByValue(value); return result != null ? result : Collections.<KtElement>emptyList(); } @NotNull @Override public List<? extends Instruction> getUsages(@Nullable PseudoValue value) { List<? extends Instruction> result = valueUsages.get(value); return result != null ? result : Collections.<Instruction>emptyList(); } @Override public boolean isSideEffectFree(@NotNull Instruction instruction) { return sideEffectFree.contains(instruction); } /*package*/ void bindElementToValue(@NotNull KtElement element, @NotNull PseudoValue value) { elementsToValues.put(element, value); } /*package*/ void bindLabel(Label label) { ((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size()); } private Set<PseudoValue> getMergedValues(@NotNull PseudoValue value) { Set<PseudoValue> result = mergedValues.get(value); return result != null ? result : Collections.<PseudoValue>emptySet(); } private void addMergedValues(@NotNull MergeInstruction instruction) { Set<PseudoValue> result = new LinkedHashSet<PseudoValue>(); for (PseudoValue value : instruction.getInputValues()) { result.addAll(getMergedValues(value)); result.add(value); } mergedValues.put(instruction.getOutputValue(), result); } private void addValueUsage(PseudoValue value, Instruction usage) { if (usage instanceof MergeInstruction) return; MapsKt.getOrPut( valueUsages, value, new Function0<List<Instruction>>() { @Override public List<Instruction> invoke() { return Lists.newArrayList(); } }) .add(usage); } public void postProcess() { if (postPrecessed) return; postPrecessed = true; errorInstruction.setSink(getSinkInstruction()); exitInstruction.setSink(getSinkInstruction()); int index = 0; for (Instruction instruction : mutableInstructionList) { // recursively invokes 'postProcess' for local declarations processInstruction(instruction, index); index++; } if (getParent() != null) return; // Collecting reachable instructions should be done after processing all instructions // (including instructions in local declarations) to avoid being in incomplete state. collectAndCacheReachableInstructions(); for (LocalFunctionDeclarationInstruction localFunctionDeclarationInstruction : getLocalDeclarations()) { ((PseudocodeImpl) localFunctionDeclarationInstruction.getBody()) .collectAndCacheReachableInstructions(); } } private void collectAndCacheReachableInstructions() { Set<Instruction> reachableInstructions = collectReachableInstructions(); for (Instruction instruction : mutableInstructionList) { if (reachableInstructions.contains(instruction)) { instructions.add(instruction); } } markDeadInstructions(); } private void processInstruction(Instruction instruction, final int currentPosition) { instruction.accept( new InstructionVisitor() { @Override public void visitInstructionWithNext(@NotNull InstructionWithNext instruction) { instruction.setNext(getNextPosition(currentPosition)); } @Override public void visitJump(@NotNull AbstractJumpInstruction instruction) { instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel())); } @Override public void visitNondeterministicJump( @NotNull NondeterministicJumpInstruction instruction) { instruction.setNext(getNextPosition(currentPosition)); List<Label> targetLabels = instruction.getTargetLabels(); for (Label targetLabel : targetLabels) { instruction.setResolvedTarget(targetLabel, getJumpTarget(targetLabel)); } } @Override public void visitConditionalJump(@NotNull ConditionalJumpInstruction instruction) { Instruction nextInstruction = getNextPosition(currentPosition); Instruction jumpTarget = getJumpTarget(instruction.getTargetLabel()); if (instruction.getOnTrue()) { instruction.setNextOnFalse(nextInstruction); instruction.setNextOnTrue(jumpTarget); } else { instruction.setNextOnFalse(jumpTarget); instruction.setNextOnTrue(nextInstruction); } visitJump(instruction); } @Override public void visitLocalFunctionDeclarationInstruction( @NotNull LocalFunctionDeclarationInstruction instruction) { PseudocodeImpl body = (PseudocodeImpl) instruction.getBody(); body.setParent(PseudocodeImpl.this); body.postProcess(); instruction.setNext(getSinkInstruction()); } @Override public void visitSubroutineExit(@NotNull SubroutineExitInstruction instruction) { // Nothing } @Override public void visitSubroutineSink(@NotNull SubroutineSinkInstruction instruction) { // Nothing } @Override public void visitInstruction(@NotNull Instruction instruction) { throw new UnsupportedOperationException(instruction.toString()); } }); } private Set<Instruction> collectReachableInstructions() { Set<Instruction> visited = Sets.newHashSet(); PseudocodeTraverserKt.traverseFollowingInstructions( getEnterInstruction(), visited, FORWARD, null); if (!visited.contains(getExitInstruction())) { visited.add(getExitInstruction()); } if (!visited.contains(errorInstruction)) { visited.add(errorInstruction); } if (!visited.contains(getSinkInstruction())) { visited.add(getSinkInstruction()); } return visited; } private void markDeadInstructions() { Set<Instruction> instructionSet = Sets.newHashSet(instructions); for (Instruction instruction : mutableInstructionList) { if (!instructionSet.contains(instruction)) { ((InstructionImpl) instruction).setMarkedAsDead(true); for (Instruction nextInstruction : instruction.getNextInstructions()) { nextInstruction.getPreviousInstructions().remove(instruction); } } } } @NotNull private Instruction getJumpTarget(@NotNull Label targetLabel) { return ((PseudocodeLabel) targetLabel).resolveToInstruction(); } @NotNull private Instruction getNextPosition(int currentPosition) { int targetPosition = currentPosition + 1; assert targetPosition < mutableInstructionList.size() : currentPosition; return mutableInstructionList.get(targetPosition); } @Override public PseudocodeImpl copy() { PseudocodeImpl result = new PseudocodeImpl(correspondingElement); result.repeatWhole(this); return result; } private void repeatWhole(@NotNull PseudocodeImpl originalPseudocode) { repeatInternal(originalPseudocode, null, null, 0); parent = originalPseudocode.parent; } public int repeatPart(@NotNull Label startLabel, @NotNull Label finishLabel, int labelCount) { return repeatInternal( ((PseudocodeLabel) startLabel).getPseudocode(), startLabel, finishLabel, labelCount); } private int repeatInternal( @NotNull PseudocodeImpl originalPseudocode, @Nullable Label startLabel, @Nullable Label finishLabel, int labelCount) { Integer startIndex = startLabel != null ? ((PseudocodeLabel) startLabel).getTargetInstructionIndex() : Integer.valueOf(0); assert startIndex != null; Integer finishIndex = finishLabel != null ? ((PseudocodeLabel) finishLabel).getTargetInstructionIndex() : Integer.valueOf(originalPseudocode.mutableInstructionList.size()); assert finishIndex != null; Map<Label, Label> originalToCopy = Maps.newLinkedHashMap(); Multimap<Instruction, Label> originalLabelsForInstruction = HashMultimap.create(); for (PseudocodeLabel label : originalPseudocode.labels) { Integer index = label.getTargetInstructionIndex(); if (index == null) continue; // label is not bounded yet if (label == startLabel || label == finishLabel) continue; if (startIndex <= index && index <= finishIndex) { originalToCopy.put(label, label.copy(labelCount++)); originalLabelsForInstruction.put(getJumpTarget(label), label); } } for (Label label : originalToCopy.values()) { labels.add((PseudocodeLabel) label); } for (int index = startIndex; index < finishIndex; index++) { Instruction originalInstruction = originalPseudocode.mutableInstructionList.get(index); repeatLabelsBindingForInstruction( originalInstruction, originalToCopy, originalLabelsForInstruction); Instruction copy = copyInstruction(originalInstruction, originalToCopy); addInstruction(copy); if (originalInstruction == originalPseudocode.errorInstruction && copy instanceof SubroutineExitInstruction) { errorInstruction = (SubroutineExitInstruction) copy; } if (originalInstruction == originalPseudocode.exitInstruction && copy instanceof SubroutineExitInstruction) { exitInstruction = (SubroutineExitInstruction) copy; } if (originalInstruction == originalPseudocode.sinkInstruction && copy instanceof SubroutineSinkInstruction) { sinkInstruction = (SubroutineSinkInstruction) copy; } } if (finishIndex < mutableInstructionList.size()) { repeatLabelsBindingForInstruction( originalPseudocode.mutableInstructionList.get(finishIndex), originalToCopy, originalLabelsForInstruction); } return labelCount; } private void repeatLabelsBindingForInstruction( @NotNull Instruction originalInstruction, @NotNull Map<Label, Label> originalToCopy, @NotNull Multimap<Instruction, Label> originalLabelsForInstruction) { for (Label originalLabel : originalLabelsForInstruction.get(originalInstruction)) { bindLabel(originalToCopy.get(originalLabel)); } } private static Instruction copyInstruction( @NotNull Instruction instruction, @NotNull Map<Label, Label> originalToCopy) { if (instruction instanceof AbstractJumpInstruction) { Label originalTarget = ((AbstractJumpInstruction) instruction).getTargetLabel(); if (originalToCopy.containsKey(originalTarget)) { return ((AbstractJumpInstruction) instruction).copy(originalToCopy.get(originalTarget)); } } if (instruction instanceof NondeterministicJumpInstruction) { List<Label> originalTargets = ((NondeterministicJumpInstruction) instruction).getTargetLabels(); List<Label> copyTargets = copyLabels(originalTargets, originalToCopy); return ((NondeterministicJumpInstruction) instruction).copy(copyTargets); } return ((InstructionImpl) instruction).copy(); } @NotNull private static List<Label> copyLabels( Collection<Label> labels, Map<Label, Label> originalToCopy) { List<Label> newLabels = Lists.newArrayList(); for (Label label : labels) { Label newLabel = originalToCopy.get(label); newLabels.add(newLabel != null ? newLabel : label); } return newLabels; } }
/** @return collection of the non-system tables */ public List<String> getNonSystemTables() { return ImmutableList.copyOf(Sets.difference(tables.keySet(), systemKeyspaceNames)); }