| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.royale.compiler.internal.mxml; |
| |
| import static org.apache.royale.compiler.constants.IMXMLCoreConstants.*; |
| |
| import java.util.Collection; |
| |
| import org.apache.royale.compiler.common.ISourceLocation; |
| import org.apache.royale.compiler.internal.parsing.ISourceFragment; |
| import org.apache.royale.compiler.internal.parsing.SourceFragment; |
| import org.apache.royale.compiler.internal.parsing.mxml.MXMLToken; |
| import org.apache.royale.compiler.mxml.IMXMLTextData; |
| import org.apache.royale.compiler.parsing.MXMLTokenTypes; |
| import org.apache.royale.compiler.problems.ICompilerProblem; |
| |
| /** |
| * Encapsulation of a block of text in MXML |
| */ |
| public class MXMLTextData extends MXMLUnitData implements IMXMLTextData |
| { |
| /** |
| * Constructor. |
| */ |
| public MXMLTextData(MXMLToken textToken) |
| { |
| text = textToken.getText(); |
| |
| setOffsets(textToken.getStart(), textToken.getEnd()); |
| setLine(textToken.getLine()); |
| setColumn(textToken.getColumn()); |
| setEndLine(textToken.getEndLine()); |
| setEndColumn(textToken.getEndColumn()); |
| |
| switch (textToken.getType()) |
| { |
| case MXMLTokenTypes.TOKEN_TEXT: |
| { |
| type = TextType.TEXT; |
| break; |
| } |
| case MXMLTokenTypes.TOKEN_WHITESPACE: |
| { |
| type = TextType.WHITESPACE; |
| break; |
| } |
| case MXMLTokenTypes.TOKEN_CDATA: |
| { |
| type = TextType.CDATA; |
| break; |
| } |
| case MXMLTokenTypes.TOKEN_COMMENT: |
| { |
| type = TextType.COMMENT; |
| break; |
| } |
| case MXMLTokenTypes.TOKEN_ASDOC_COMMENT: |
| { |
| type = TextType.ASDOC; |
| break; |
| } |
| } |
| } |
| |
| /** |
| * The represented text |
| */ |
| private String text; |
| |
| private TextType type; |
| |
| // |
| // Object overrides |
| // |
| |
| // For debugging only. This format is nice in the Eclipse debugger. |
| @Override |
| public String toString() |
| { |
| StringBuilder sb = new StringBuilder(); |
| |
| // Display TEXT, WHITESPACE, etc. |
| sb.append(getTextType()); |
| |
| sb.append(' '); |
| |
| // Display the text characters. |
| sb.append('"'); |
| sb.append(getEscapedContent()); |
| sb.append('"'); |
| |
| sb.append(' '); |
| |
| // Display line, column, start, and end as "17:5 160-188". |
| sb.append(super.toString()); |
| |
| return sb.toString(); |
| } |
| |
| // |
| // MXMLUnitData overrides |
| // |
| |
| @Override |
| public boolean isText() |
| { |
| return true; |
| } |
| |
| // For debugging only. |
| @Override |
| public String getTypeString() |
| { |
| StringBuilder sb = new StringBuilder(); |
| |
| sb.append(super.getTypeString()); |
| sb.append(":"); |
| sb.append(getTextType()); |
| |
| return sb.toString(); |
| } |
| |
| // For debugging only. This format is nice in a text file. |
| @Override |
| public String toDumpString() |
| { |
| StringBuilder sb = new StringBuilder(); |
| |
| sb.append(super.toDumpString()); |
| |
| sb.append('\t'); |
| |
| sb.append('|'); |
| sb.append(getEscapedContent()); |
| sb.append('|'); |
| |
| return sb.toString(); |
| } |
| |
| // |
| // IMXMLTextData implementations |
| // |
| |
| @Override |
| public String getContent() |
| { |
| return text; |
| } |
| |
| @Override |
| public TextType getTextType() |
| { |
| return type; |
| } |
| |
| // |
| // Other methods |
| // |
| |
| // For debugging only. |
| private String getEscapedContent() |
| { |
| String s = getContent(); |
| |
| s = s.replaceAll("\n", "\\\\n"); |
| s = s.replaceAll("\r", "\\\\r"); |
| s = s.replaceAll("\t", "\\\\t"); |
| |
| return s; |
| } |
| |
| @Override |
| public String getCompilableText() |
| { |
| switch (type) |
| { |
| case TEXT: |
| case CDATA: |
| case WHITESPACE: |
| { |
| return getContents(); |
| } |
| |
| case ASDOC: |
| case COMMENT: |
| { |
| return ""; |
| } |
| } |
| |
| assert false; |
| return null; |
| } |
| |
| @Override |
| public int getCompilableTextStart() |
| { |
| return getContentsStart(); |
| } |
| |
| @Override |
| public int getCompilableTextEnd() |
| { |
| return getContentsEnd(); |
| } |
| |
| @Override |
| public int getCompilableTextLine() |
| { |
| return getLine(); |
| } |
| |
| @Override |
| public int getCompilableTextColumn() |
| { |
| return (getContentsStart() - getAbsoluteStart()) + getColumn(); |
| } |
| |
| /** |
| * Return the text contained within this unit, without any opening or |
| * closing delimiters |
| * |
| * @return a normalized string |
| */ |
| public String getContents() |
| { |
| String tokenString = text; |
| |
| switch (type) |
| { |
| case CDATA: |
| { |
| if (tokenString.endsWith(cDataEnd)) |
| { |
| tokenString = tokenString.substring(cDataStart.length(), tokenString.length() - cDataEnd.length()); |
| } |
| else |
| { |
| tokenString = tokenString.substring(cDataStart.length()); |
| } |
| return tokenString; |
| } |
| case ASDOC: |
| { |
| if (tokenString.endsWith(asDocEnd)) |
| { |
| tokenString = tokenString.substring(asDocStart.length(), tokenString.length() - asDocEnd.length()); |
| } |
| else |
| { |
| tokenString = tokenString.substring(asDocStart.length()); |
| } |
| return tokenString; |
| } |
| case COMMENT: |
| { |
| if (tokenString.endsWith(commentEnd)) |
| { |
| tokenString = tokenString.substring(commentStart.length(), tokenString.length() - commentEnd.length()); |
| } |
| else |
| { |
| tokenString = tokenString.substring(commentStart.length()); |
| } |
| return tokenString; |
| } |
| default: |
| { |
| break; |
| } |
| } |
| |
| return text; |
| } |
| |
| /** |
| * @return The start offset of actual content |
| */ |
| public int getContentsStart() |
| { |
| switch (type) |
| { |
| case CDATA: |
| return getAbsoluteStart() + cDataStart.length(); |
| |
| case ASDOC: |
| return getAbsoluteStart() + asDocStart.length(); |
| |
| case COMMENT: |
| return getAbsoluteStart() + commentStart.length(); |
| } |
| |
| return getAbsoluteStart(); |
| } |
| |
| /** |
| * @return The end offset of content |
| */ |
| public int getContentsEnd() |
| { |
| switch (type) |
| { |
| case CDATA: |
| return text.endsWith(cDataEnd) ? getAbsoluteEnd() - cDataEnd.length() : getAbsoluteEnd(); |
| |
| case ASDOC: |
| return text.endsWith(asDocEnd) ? getAbsoluteEnd() - asDocEnd.length() : getAbsoluteEnd(); |
| |
| case COMMENT: |
| return text.endsWith(commentEnd) ? getAbsoluteEnd() - commentEnd.length() : getAbsoluteEnd(); |
| } |
| |
| return getAbsoluteEnd(); |
| } |
| |
| public int getContentsLine() |
| { |
| return getLine(); |
| } |
| |
| public int getContentsColumn() |
| { |
| switch (type) |
| { |
| case CDATA: |
| return getColumn() + cDataStart.length(); |
| |
| case ASDOC: |
| return getColumn() + asDocStart.length(); |
| |
| case COMMENT: |
| return getColumn() + commentStart.length(); |
| } |
| |
| return getColumn(); |
| } |
| |
| @Override |
| public ISourceFragment[] getFragments(Collection<ICompilerProblem> problems) |
| { |
| ISourceLocation location = this; |
| |
| switch (type) |
| { |
| case TEXT: |
| { |
| // TEXT might contain one or more entities, |
| // in which case we will return multiple fragments. |
| MXMLDialect mxmlDialect = getMXMLDialect(); |
| return EntityProcessor.parse(text, location, mxmlDialect, problems); |
| } |
| |
| case WHITESPACE: |
| { |
| // WHITESPACE creates only a single fragment. |
| ISourceFragment fragment = new SourceFragment(text, location); |
| return new ISourceFragment[] {fragment}; |
| } |
| |
| case CDATA: |
| { |
| // CDATA creates only a single fragment. |
| ISourceFragment fragment = new SourceFragment(text, getContents(), getContentsStart(), getContentsLine(), getContentsColumn()); |
| return new ISourceFragment[] {fragment}; |
| } |
| |
| default: |
| { |
| assert false : "Unexpected type of MXMLTextData"; |
| } |
| } |
| |
| return null; |
| } |
| } |