| /******************************************************************************* |
| * Copyright (c) 2004, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.css.core.internal.document; |
| |
| import java.util.Iterator; |
| import java.util.Vector; |
| |
| import org.eclipse.wst.css.core.internal.parserz.CSSRegionContexts; |
| import org.eclipse.wst.css.core.internal.provisional.document.ICSSAttr; |
| import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode; |
| import org.eclipse.wst.css.core.internal.provisional.document.ICSSNodeList; |
| import org.eclipse.wst.css.core.internal.provisional.document.ICSSRuleContainer; |
| import org.eclipse.wst.css.core.internal.util.CSSUtil; |
| import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; |
| import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; |
| import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; |
| |
| /** |
| * |
| */ |
| class CSSModelUtil { |
| |
| /** |
| * |
| */ |
| static boolean canContainBrace(ICSSNode node) { |
| return (node != null && (node instanceof ICSSRuleContainer || node instanceof CSSRuleDeclContainer)) ? true : false; |
| } |
| |
| /** |
| * @param parent |
| * org.eclipse.wst.css.core.model.interfaces.ICSSNode |
| */ |
| static void cleanupContainer(ICSSNode parent) { |
| if (parent == null) { |
| return; |
| } |
| for (ICSSNode child = parent.getFirstChild(); child != null; child = child.getNextSibling()) { |
| cleanupContainer(child); |
| } |
| if (parent instanceof CSSStructuredDocumentRegionContainer) { |
| ((CSSStructuredDocumentRegionContainer) parent).setRangeStructuredDocumentRegion(null, null); |
| } |
| else if (parent instanceof CSSRegionContainer) { |
| ((CSSRegionContainer) parent).setRangeRegion(null, null, null); |
| } |
| } |
| |
| static boolean diagnoseNode(ICSSNode parent, IStructuredDocument structuredDocument) { |
| // check this |
| Vector errors = new Vector(); |
| if (parent instanceof CSSStructuredDocumentRegionContainer) { |
| CSSStructuredDocumentRegionContainer node = (CSSStructuredDocumentRegionContainer) parent; |
| String nodeText = CSSUtil.getClassString(node) + ": ";//$NON-NLS-1$ |
| IStructuredDocumentRegion flatNode = node.getFirstStructuredDocumentRegion(); |
| if (flatNode == null && (!(node instanceof CSSStyleDeclarationImpl || node instanceof CSSStyleSheetImpl) || node.getFirstChild() != null)) { |
| errors.add(nodeText + "first flat node is null."); //$NON-NLS-1$ |
| } |
| else if (flatNode != null) { |
| IStructuredDocumentRegion modelNode = structuredDocument.getRegionAtCharacterOffset(flatNode.getStart()); |
| if (flatNode != modelNode) { |
| errors.add(nodeText + "first flat node is not in model."); //$NON-NLS-1$ |
| } |
| } |
| flatNode = node.getLastStructuredDocumentRegion(); |
| if (flatNode == null && (!(node instanceof CSSStyleDeclarationImpl || node instanceof CSSStyleSheetImpl) || node.getFirstChild() != null)) { |
| errors.add(nodeText + "last flat node is null."); //$NON-NLS-1$ |
| } |
| else if (flatNode != null) { |
| IStructuredDocumentRegion modelNode = structuredDocument.getRegionAtCharacterOffset(flatNode.getStart()); |
| if (flatNode != modelNode) { |
| errors.add(nodeText + "last flat node is not in model."); //$NON-NLS-1$ |
| } |
| } |
| } |
| else if (parent instanceof CSSRegionContainer) { |
| CSSRegionContainer node = (CSSRegionContainer) parent; |
| String nodeText = CSSUtil.getClassString(node) + ": ";//$NON-NLS-1$ |
| ITextRegion region = node.getFirstRegion(); |
| IStructuredDocumentRegion parentRegion = node.getDocumentRegion(); |
| if (region == null && (!(node instanceof MediaListImpl) || node.getFirstChild() != null)) { |
| errors.add(nodeText + "first region is null."); //$NON-NLS-1$ |
| } |
| else if (region != null) { |
| int offset = parentRegion.getStartOffset(region); |
| IStructuredDocumentRegion modelNode = structuredDocument.getRegionAtCharacterOffset(offset); |
| ITextRegion modelRegion = modelNode.getRegionAtCharacterOffset(offset); |
| if (region != modelRegion) { |
| errors.add(nodeText + "first region is not in model."); //$NON-NLS-1$ |
| } |
| } |
| region = node.getLastRegion(); |
| if (region == null && (!(node instanceof MediaListImpl) || node.getFirstChild() != null)) { |
| errors.add(nodeText + "last region is null."); //$NON-NLS-1$ |
| } |
| else if (region != null) { |
| int offset = parentRegion.getStartOffset(region); |
| IStructuredDocumentRegion modelNode = structuredDocument.getRegionAtCharacterOffset(offset); |
| ITextRegion modelRegion = modelNode.getRegionAtCharacterOffset(offset); |
| if (region != modelRegion) { |
| errors.add(nodeText + "last region is not in model."); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| ICSSNodeList attrs = parent.getAttributes(); |
| int nAttrs = attrs.getLength(); |
| for (int i = 0; i < nAttrs; i++) { |
| ICSSAttr attr = (ICSSAttr) attrs.item(i); |
| CSSRegionContainer node = (CSSRegionContainer) attr; |
| String nodeText = CSSUtil.getClassString(node) + "(" + attr.getName() + "): ";//$NON-NLS-2$//$NON-NLS-1$ |
| ITextRegion region = node.getFirstRegion(); |
| IStructuredDocumentRegion parentRegion = node.getDocumentRegion(); |
| if (region == null && 0 < attr.getValue().length()) { |
| errors.add(nodeText + "first region is null."); //$NON-NLS-1$ |
| } |
| else if (region != null) { |
| int offset = parentRegion.getStartOffset(region); |
| IStructuredDocumentRegion modelNode = structuredDocument.getRegionAtCharacterOffset(offset); |
| ITextRegion modelRegion = modelNode.getRegionAtCharacterOffset(offset); |
| if (region != modelRegion) { |
| errors.add(nodeText + "first region is not in model."); //$NON-NLS-1$ |
| } |
| } |
| region = node.getLastRegion(); |
| if (region == null && 0 < attr.getValue().length()) { |
| errors.add(nodeText + "last region is null."); //$NON-NLS-1$ |
| } |
| else if (region != null) { |
| int offset = parentRegion.getStartOffset(region); |
| IStructuredDocumentRegion modelNode = structuredDocument.getRegionAtCharacterOffset(offset); |
| ITextRegion modelRegion = modelNode.getRegionAtCharacterOffset(offset); |
| if (region != modelRegion) { |
| errors.add(nodeText + "last region is not in model."); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| if (!errors.isEmpty()) { |
| Iterator i = errors.iterator(); |
| while (i.hasNext()) { |
| CSSUtil.debugOut((String) i.next()); |
| } |
| return false; |
| } |
| else { |
| return true; |
| } |
| } |
| |
| /** |
| * @return boolean |
| * @param node |
| * org.eclipse.wst.css.core.model.interfaces.ICSSNode |
| */ |
| static boolean diagnoseTree(ICSSNode parent, IStructuredDocument structuredDocument) { |
| if (parent == null) { |
| return false; |
| } |
| // check children |
| for (ICSSNode child = parent.getFirstChild(); child != null; child = child.getNextSibling()) { |
| diagnoseTree(child, structuredDocument); |
| } |
| |
| diagnoseNode(parent, structuredDocument); |
| |
| return true; |
| } |
| |
| /** |
| * If needed, modify last flat node |
| */ |
| static void expandStructuredDocumentRegionContainer(CSSStructuredDocumentRegionContainer target, IStructuredDocumentRegion flatNode) { |
| if (target == null || flatNode == null) { |
| return; |
| } |
| |
| IStructuredDocumentRegion lastNode = target.getLastStructuredDocumentRegion(); |
| if (lastNode == flatNode) { |
| return; |
| } |
| if (lastNode == null || lastNode.getStart() < flatNode.getStart()) { |
| target.setLastStructuredDocumentRegion(flatNode); |
| } |
| } |
| |
| /* |
| * |
| */ |
| static ICSSNode findBraceContainer(ICSSNode node) { |
| for (ICSSNode i = node; i != null; i = i.getParentNode()) { |
| if (CSSModelUtil.canContainBrace(i)) { |
| return i; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * |
| */ |
| static int getDepth(ICSSNode node) { |
| int depth = -1; |
| while (node != null) { |
| depth++; |
| node = node.getParentNode(); |
| } |
| return depth; |
| } |
| |
| /** |
| * |
| */ |
| static boolean isBraceClosed(ICSSNode node) { |
| boolean bClosed = true; |
| if (!(node instanceof CSSStructuredDocumentRegionContainer)) { |
| return bClosed; |
| } |
| |
| IStructuredDocumentRegion first = ((CSSStructuredDocumentRegionContainer) node).getFirstStructuredDocumentRegion(); |
| IStructuredDocumentRegion last = ((CSSStructuredDocumentRegionContainer) node).getLastStructuredDocumentRegion(); |
| if (first == null || last == null) { |
| return bClosed; |
| } |
| if (last.getStart() < first.getStart()) { |
| return bClosed; |
| } |
| |
| IStructuredDocumentRegion flatNode = first; |
| int nOpen = 0; |
| int nClose = 0; |
| do { |
| String type = CSSUtil.getStructuredDocumentRegionType(flatNode); |
| if (type == CSSRegionContexts.CSS_LBRACE) { |
| nOpen++; |
| } |
| else if (type == CSSRegionContexts.CSS_RBRACE) { |
| nClose++; |
| } |
| flatNode = flatNode.getNext(); |
| } |
| while (flatNode != null && flatNode != last); |
| |
| if ((nOpen == 0 && nClose == 0) || nClose < nOpen) { |
| bClosed = false; |
| } |
| |
| return bClosed; |
| } |
| |
| /** |
| * only for insertion.. |
| */ |
| static boolean isInterruption(CSSStructuredDocumentRegionContainer target, IStructuredDocumentRegion flatNode) { |
| if (target == null || flatNode == null) { |
| return false; |
| } |
| int start = flatNode.getStart(); |
| IStructuredDocumentRegion firstNode = target.getFirstStructuredDocumentRegion(); |
| IStructuredDocumentRegion lastNode = target.getLastStructuredDocumentRegion(); |
| if (firstNode != null && firstNode.getStart() < start && lastNode != null && start < lastNode.getStart()) { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * |
| */ |
| static boolean isParentOf(ICSSNode parent, ICSSNode child) { |
| if (parent == null || child == null) { |
| return false; |
| } |
| |
| for (ICSSNode node = child; node != null; node = node.getParentNode()) { |
| if (parent == node) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| } |