/* * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.psi.impl.source.tree; import com.intellij.lang.ASTNode; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; import com.intellij.util.text.CharArrayCharSequence; import com.intellij.util.text.StringFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @author max */ public class AstBufferUtil { private AstBufferUtil() { } public static int toBuffer(@NotNull ASTNode element, @Nullable char[] buffer, int offset) { return toBuffer(element, buffer, offset, false); } public static int toBuffer(@NotNull ASTNode element, @Nullable char[] buffer, int offset, boolean skipWhitespaceAndComments) { BufferVisitor visitor = new BufferVisitor(skipWhitespaceAndComments, skipWhitespaceAndComments, offset, buffer); ((TreeElement)element).acceptTree(visitor); return visitor.end; } public static String getTextSkippingWhitespaceComments(@NotNull ASTNode element) { int length = toBuffer(element, null, 0, true); char[] buffer = new char[length]; toBuffer(element, buffer, 0, true); return StringFactory.createShared(buffer); } public static class BufferVisitor extends RecursiveTreeElementWalkingVisitor { private final boolean skipWhitespace; private final boolean skipComments; protected final int offset; protected int end; protected final char[] buffer; public BufferVisitor(PsiElement element, boolean skipWhitespace, boolean skipComments) { this(skipWhitespace, skipComments, 0, new char[element.getTextLength()]); ((TreeElement)element.getNode()).acceptTree(this); } public BufferVisitor(boolean skipWhitespace, boolean skipComments, int offset, @Nullable char[] buffer) { super(false); this.skipWhitespace = skipWhitespace; this.skipComments = skipComments; this.buffer = buffer; this.offset = offset; end = offset; } public int getEnd() { return end; } public char[] getBuffer() { assert buffer != null; return buffer; } public CharSequence createCharSequence() { assert buffer != null; return new CharArrayCharSequence(buffer, offset, end); } @Override public void visitLeaf(LeafElement element) { ProgressIndicatorProvider.checkCanceled(); if (!isIgnored(element)) { end = element.copyTo(buffer, end); } } protected boolean isIgnored(LeafElement element) { return element instanceof ForeignLeafPsiElement || (skipWhitespace && element instanceof PsiWhiteSpace) || (skipComments && element instanceof PsiComment); } @Override public void visitComposite(CompositeElement composite) { if (composite instanceof LazyParseableElement) { LazyParseableElement lpe = (LazyParseableElement)composite; int lpeResult = lpe.copyTo(buffer, end); if (lpeResult >= 0) { end = lpeResult; return; } assert lpe.isParsed(); } super.visitComposite(composite); } } }