@NotNull public static String getElementTextWithContext(@NotNull JetElement element) { if (element instanceof JetFile) { return element.getContainingFile().getText(); } // Find parent for element among file children PsiElement inFileParent = PsiTreeUtil.findFirstParent( element, new Condition<PsiElement>() { @Override public boolean value(PsiElement parentCandidate) { return parentCandidate != null && parentCandidate.getParent() instanceof JetFile; } }); assert inFileParent != null : "For non-file element we should always be able to find parent in file children"; int startContextOffset = inFileParent.getTextRange().getStartOffset(); int elementContextOffset = element.getTextRange().getStartOffset(); int inFileParentOffset = elementContextOffset - startContextOffset; return new StringBuilder(inFileParent.getText()) .insert(inFileParentOffset, "<caret>") .toString(); }
public static <D> void visitChildren( @NotNull JetElement element, @NotNull JetTreeVisitor<D> visitor, D data) { PsiElement child = element.getFirstChild(); while (child != null) { if (child instanceof JetElement) { ((JetElement) child).accept(visitor, data); } child = child.getNextSibling(); } }
@Nullable public static JetElement getOutermostDescendantElement( @Nullable PsiElement root, boolean first, final @NotNull Predicate<JetElement> predicate) { if (!(root instanceof JetElement)) return null; final List<JetElement> results = Lists.newArrayList(); ((JetElement) root) .accept( new JetVisitorVoid() { @Override public void visitJetElement(@NotNull JetElement element) { if (predicate.apply(element)) { //noinspection unchecked results.add(element); } else { element.acceptChildren(this); } } }); if (results.isEmpty()) return null; return first ? results.get(0) : results.get(results.size() - 1); }
@Nullable public static String getPackageName(@NotNull JetElement element) { JetFile file = (JetFile) element.getContainingFile(); JetNamespaceHeader header = PsiTreeUtil.findChildOfType(file, JetNamespaceHeader.class); return header != null ? header.getQualifiedName() : null; }
@NotNull public static Set<JetElement> findRootExpressions( @NotNull Collection<JetElement> unreachableElements) { Set<JetElement> rootElements = new HashSet<JetElement>(); final Set<JetElement> shadowedElements = new HashSet<JetElement>(); JetVisitorVoid shadowAllChildren = new JetVisitorVoid() { @Override public void visitJetElement(@NotNull JetElement element) { if (shadowedElements.add(element)) { element.acceptChildren(this); } } }; for (JetElement element : unreachableElements) { if (shadowedElements.contains(element)) continue; element.acceptChildren(shadowAllChildren); rootElements.removeAll(shadowedElements); rootElements.add(element); } return rootElements; }
public static boolean isImplicitlyUsed(@NotNull JetElement element) { PsiElement parent = element.getParent(); if (!(parent instanceof JetBlockExpression)) return true; JetBlockExpression block = (JetBlockExpression) parent; List<JetElement> statements = block.getStatements(); if (statements.get(statements.size() - 1) == element) { JetExpression expression = getDirectParentOfTypeForBlock(block, JetIfExpression.class); if (expression == null) { expression = getDirectParentOfTypeForBlock(block, JetWhenExpression.class); } if (expression == null) { expression = getDirectParentOfTypeForBlock(block, JetFunctionLiteral.class); } if (expression == null) { expression = getDirectParentOfTypeForBlock(block, JetTryExpression.class); } if (expression != null) { return isImplicitlyUsed(expression); } } return false; }
private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) { MethodNode node = nodeAndSmap.getNode(); ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions); generateClosuresBodies(); // through generation captured parameters will be added to invocationParamBuilder putClosureParametersOnStack(); addInlineMarker(codegen.v, true); Parameters parameters = invocationParamBuilder.buildParameters(); InliningContext info = new RootInliningContext( expressionMap, state, codegen.getInlineNameGenerator().subGenerator(functionDescriptor.getName().asString()), codegen.getContext(), callElement, codegen.getParentCodegen().getClassName(), reifiedTypeInliner); MethodInliner inliner = new MethodInliner( node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule, "Method inlining " + callElement.getText(), createNestedSourceMapper(nodeAndSmap)); // with captured LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize); MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode(); // hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain adapter.visitInsn(Opcodes.NOP); InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL); result.getReifiedTypeParametersUsages().mergeAll(reificationResult); CallableMemberDescriptor descriptor = codegen.getContext().getContextDescriptor(); final Set<String> labels = getDeclarationLabels( DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor); LabelOwner labelOwner = new LabelOwner() { @Override public boolean isMyLabel(@NotNull String name) { return labels.contains(name); } }; List<MethodInliner.PointForExternalFinallyBlocks> infos = MethodInliner.processReturns(adapter, labelOwner, true, null); generateAndInsertFinallyBlocks( adapter, infos, ((StackValue.Local) remapper.remap(parameters.totalSize() + 1).value).index); removeFinallyMarkers(adapter); adapter.accept(new InliningInstructionAdapter(codegen.v)); addInlineMarker(codegen.v, false); return result; }