Search in sources :

Example 21 with ITextRegion

use of org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion in project webtools.sourceediting by eclipse.

the class HTMLAttributeValidator method validate.

/**
 */
public void validate(IndexedRegion node) {
    Element target = (Element) node;
    if (CMUtil.isForeign(target))
        return;
    CMElementDeclaration edec = CMUtil.getDeclaration(target);
    if (edec == null) {
        NamedNodeMap attrs = target.getAttributes();
        // unknown tag - go to validators from extension point
        for (int i = 0; i < attrs.getLength(); i++) {
            Attr a = (Attr) attrs.item(i);
            final String attrName = a.getName().toLowerCase(Locale.US);
            // Check for user-defined exclusions
            if (shouldValidateAttributeName(target, attrName)) {
                validateWithExtension(target, a, attrName);
            }
        }
    } else {
        CMNamedNodeMap declarations = edec.getAttributes();
        List modelQueryNodes = null;
        NamedNodeMap attrs = target.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            int rgnType = REGION_NAME;
            int state = ErrorState.NONE_ERROR;
            Attr a = (Attr) attrs.item(i);
            // D203637; If the target attr has prefix, the validator should
            // not
            // warn about it. That is, just ignore. It is able to check
            // whether
            // an attr has prefix or not by calling XMLAttr#isGlobalAttr().
            // When a attr has prefix (not global), it returns false.
            boolean isXMLAttr = a instanceof IDOMAttr;
            if (isXMLAttr) {
                IDOMAttr xmlattr = (IDOMAttr) a;
                if (!xmlattr.isGlobalAttr() || xmlattr.getNameRegion() instanceof ITextRegionContainer)
                    // skip futher validation and begin next loop.
                    continue;
            }
            CMAttributeDeclaration adec = (CMAttributeDeclaration) declarations.getNamedItem(a.getName());
            final String attrName = a.getName().toLowerCase(Locale.US);
            /* Check the modelquery if nothing is declared by the element declaration */
            if (adec == null) {
                if (modelQueryNodes == null)
                    modelQueryNodes = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getAvailableContent((Element) node, edec, ModelQuery.INCLUDE_ATTRIBUTES);
                for (int k = 0; k < modelQueryNodes.size(); k++) {
                    CMNode cmnode = (CMNode) modelQueryNodes.get(k);
                    if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION && cmnode.getNodeName().toLowerCase(Locale.US).equals(attrName)) {
                        adec = (CMAttributeDeclaration) cmnode;
                        break;
                    }
                }
            }
            if (adec == null) {
                if ((attrName.startsWith(ATTR_NAME_DATA) && attrName.length() > ATTR_NAME_DATA_LENGTH) || (attrName.startsWith(ATTR_NAME_USER_AGENT_FEATURE) && attrName.length() > ATTR_NAME_USER_AGENT_FEATURE_LENGTH) || (attrName.startsWith(ATTR_NAME_WAI_ARIA) && attrName.length() > ATTR_NAME_WAI_ARIA_LENGTH)) {
                    if (isHTML5(target))
                        continue;
                }
                // Check for user-defined exclusions
                if (!shouldValidateAttributeName(target, attrName))
                    continue;
                // No attr declaration was found. That is, the attr name is
                // undefined.
                // but not regard it as undefined name if it includes nested
                // region
                // Then look into extension point for external validator
                validateWithExtension(target, a, attrName);
            } else {
                // At 1st, the name should be checked.
                if (CMUtil.isObsolete(adec)) {
                    state = ErrorState.OBSOLETE_ATTR_NAME_ERROR;
                }
                if (CMUtil.isHTML(edec) && (!CMUtil.isXHTML(edec))) {
                    // specifically.
                    if (CMUtil.isBooleanAttr(adec) && ((IDOMAttr) a).hasNameOnly())
                        // OK, keep going. No more check is needed
                        continue;
                // against this attr.
                } else {
                    // If the target is other than pure HTML (JSP or XHTML),
                    // the name
                    // must be checked exactly (ie in case sensitive way).
                    String actual = a.getName();
                    String desired = adec.getAttrName();
                    if (!actual.equals(desired)) {
                        // case mismatch
                        rgnType = REGION_NAME;
                        state = ErrorState.MISMATCHED_ERROR;
                    }
                }
                // Then, the value must be checked.
                if (state == ErrorState.NONE_ERROR) {
                    // Need more check.
                    // Now, the value should be checked, if the type is ENUM.
                    CMDataType attrType = adec.getAttrType();
                    if (a instanceof IDOMAttr) {
                        final ITextRegion region = ((IDOMAttr) a).getEqualRegion();
                        if (region == null) {
                            rgnType = REGION_NAME;
                            state = ErrorState.MISSING_ATTR_VALUE_EQUALS_ERROR;
                        }
                    }
                    String actualValue = a.getValue();
                    if (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) {
                        // Check FIXED value.
                        String validValue = attrType.getImpliedValue();
                        if (!actualValue.equals(validValue)) {
                            rgnType = REGION_VALUE;
                            state = ErrorState.UNDEFINED_VALUE_ERROR;
                        }
                    } else if (CMDataType.URI.equals(attrType.getDataTypeName())) {
                        if (actualValue.indexOf('#') < 0 && actualValue.indexOf(":/") < 0 && !actualValue.toLowerCase(Locale.ENGLISH).startsWith(JAVASCRIPT_PREFIX) && CMUtil.isHTML(edec)) {
                            // $NON-NLS-1$ //$NON-NLS-2$
                            IStructuredDocumentRegion start = ((IDOMNode) node).getStartStructuredDocumentRegion();
                            // roundabout start tag check
                            if (start != null && start.getFirstRegion().getTextLength() == 1) {
                                // only check when we have a way to set dependencies
                                Collection dependencies = (Collection) ((IDOMNode) ((IDOMNode) node).getOwnerDocument()).getUserData(HTMLValidationAdapterFactory.DEPENDENCIES);
                                if (dependencies != null) {
                                    IPath basePath = new Path(((IDOMNode) node).getModel().getBaseLocation());
                                    if (basePath.segmentCount() > 1) {
                                        IPath path = ModuleCoreSupport.resolve(basePath, actualValue);
                                        IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
                                        if (found != null) {
                                            dependencies.add(found);
                                        }
                                    }
                                }
                            }
                        }
                    } else if (CMDataType.ENUM.equals(attrType.getDataTypeName())) {
                        /*
							 * Check current value is valid among a known list.
							 * There may be enumerated values provided even when
							 * the datatype is not ENUM, but we'll only validate
							 * against that list if the type matches.
							 */
                        String[] enumeratedValues = attrType.getEnumeratedValues();
                        // several candidates are found.
                        boolean found = false;
                        for (int j = 0; j < enumeratedValues.length; j++) {
                            // At 1st, compare ignoring case.
                            if (actualValue.equalsIgnoreCase(enumeratedValues[j])) {
                                found = true;
                                if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(enumeratedValues[j]))) {
                                    rgnType = REGION_VALUE;
                                    state = ErrorState.MISMATCHED_VALUE_ERROR;
                                }
                                // exit the loop.
                                break;
                            }
                        }
                        if (!found) {
                            // retrieve and check extended values (retrieval can call extensions, which may take longer)
                            String[] modelQueryExtensionValues = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getPossibleDataTypeValues((Element) node, adec);
                            // copied loop from above
                            for (int j = 0; j < modelQueryExtensionValues.length; j++) {
                                // At 1st, compare ignoring case.
                                if (actualValue.equalsIgnoreCase(modelQueryExtensionValues[j])) {
                                    found = true;
                                    if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(modelQueryExtensionValues[j]))) {
                                        rgnType = REGION_VALUE;
                                        state = ErrorState.MISMATCHED_VALUE_ERROR;
                                    }
                                    // exit the loop.
                                    break;
                                }
                            }
                            // includes nested region.
                            if (!hasNestedRegion(((IDOMNode) a).getValueRegion())) {
                                rgnType = REGION_VALUE;
                                state = ErrorState.UNDEFINED_VALUE_ERROR;
                            }
                        }
                    }
                }
                // <<D210422
                if (state == ErrorState.NONE_ERROR) {
                    // Need more check.
                    if (isXMLAttr) {
                        String source = ((IDOMAttr) a).getValueRegionText();
                        if (source != null) {
                            char firstChar = source.charAt(0);
                            char lastChar = source.charAt(source.length() - 1);
                            boolean unclosedAttr = false;
                            if (isQuote(firstChar) || isQuote(lastChar)) {
                                if (lastChar != firstChar) {
                                    unclosedAttr = true;
                                }
                            } else {
                                if (CMUtil.isXHTML(edec)) {
                                    unclosedAttr = true;
                                }
                            }
                            if (unclosedAttr) {
                                rgnType = REGION_VALUE;
                                state = ErrorState.UNCLOSED_ATTR_VALUE;
                            }
                        }
                    }
                }
            // D210422
            }
            if (state != ErrorState.NONE_ERROR) {
                Segment seg = getErrorSegment((IDOMNode) a, rgnType);
                if (seg != null)
                    reporter.report(new ErrorInfoImpl(state, seg, a));
            }
        }
    }
}
Also used : IDOMAttr(org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr) IStructuredDocumentRegion(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion) CMDataType(org.eclipse.wst.xml.core.internal.contentmodel.CMDataType) IConfigurationElement(org.eclipse.core.runtime.IConfigurationElement) Element(org.w3c.dom.Element) IDOMElement(org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement) Attr(org.w3c.dom.Attr) IDOMAttr(org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr) IDOMNode(org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode) List(java.util.List) ITextRegionList(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList) ArrayList(java.util.ArrayList) IPath(org.eclipse.core.runtime.IPath) Path(org.eclipse.core.runtime.Path) CMNamedNodeMap(org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap) NamedNodeMap(org.w3c.dom.NamedNodeMap) IPath(org.eclipse.core.runtime.IPath) ITextRegionContainer(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer) CMElementDeclaration(org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration) ITextRegion(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion) Collection(java.util.Collection) CMAttributeDeclaration(org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration) CMNode(org.eclipse.wst.xml.core.internal.contentmodel.CMNode) CMNamedNodeMap(org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap) IResource(org.eclipse.core.resources.IResource)

Example 22 with ITextRegion

use of org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion in project webtools.sourceediting by eclipse.

the class HTMLAttributeValidator method getErrorSegment.

/**
 */
public static Segment getErrorSegment(IDOMNode errorNode, int regionType) {
    ITextRegion rgn = null;
    switch(regionType) {
        case REGION_NAME:
            rgn = errorNode.getNameRegion();
            break;
        case REGION_VALUE:
            rgn = errorNode.getValueRegion();
            break;
        default:
            // nothing to do.
            break;
    }
    if (rgn != null) {
        if (errorNode instanceof IDOMAttr) {
            IDOMElement ownerElement = (IDOMElement) ((IDOMAttr) errorNode).getOwnerElement();
            if (ownerElement != null) {
                // if editor closed during validation this could be null
                IStructuredDocumentRegion firstRegion = ownerElement.getFirstStructuredDocumentRegion();
                if (firstRegion != null) {
                    int regionStartOffset = firstRegion.getStartOffset(rgn);
                    int regionLength = rgn.getTextLength();
                    return new Segment(regionStartOffset, regionLength);
                }
            }
        }
    }
    return new Segment(errorNode.getStartOffset(), 1);
}
Also used : IDOMAttr(org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr) IStructuredDocumentRegion(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion) ITextRegion(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion) IDOMElement(org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement)

Example 23 with ITextRegion

use of org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion in project webtools.sourceediting by eclipse.

the class StructuredTextPartitionerForHTML method getPartitionTypeBetween.

public String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, IStructuredDocumentRegion nextNode) {
    ITextRegion previousStartTagNameRegion = null;
    ITextRegion nextEndTagNameRegion = null;
    ITextRegion[] regions = previousNode.getRegions().toArray();
    for (int i = 0; i < regions.length; i++) {
        if (regions[i].getType() == DOMRegionContext.XML_TAG_NAME) {
            previousStartTagNameRegion = regions[i];
            break;
        }
    }
    regions = nextNode.getRegions().toArray();
    for (int i = 0; i < regions.length; i++) {
        if (regions[i].getType() == DOMRegionContext.XML_TAG_NAME) {
            nextEndTagNameRegion = regions[i];
            break;
        }
    }
    if (previousStartTagNameRegion == null || nextEndTagNameRegion == null)
        return IHTMLPartitions.HTML_DEFAULT;
    String name1 = previousNode.getText(previousStartTagNameRegion);
    String name2 = nextNode.getText(nextEndTagNameRegion);
    if (name1.equalsIgnoreCase(HTML40Namespace.ElementName.SCRIPT) && name2.equalsIgnoreCase(HTML40Namespace.ElementName.SCRIPT))
        // return ST_SCRIPT;
        return getScriptingPartitionType(fStructuredDocument.getRegionAtCharacterOffset(previousNode.getStartOffset(previousStartTagNameRegion)));
    else if (name1.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE) && name2.equalsIgnoreCase(HTML40Namespace.ElementName.STYLE))
        return getStylePartitionType(fStructuredDocument.getRegionAtCharacterOffset(previousNode.getStartOffset(previousStartTagNameRegion)));
    return super.getPartitionTypeBetween(previousNode, nextNode);
}
Also used : ITextRegion(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion)

Example 24 with ITextRegion

use of org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion in project webtools.sourceediting by eclipse.

the class StructuredTextPartitionerForHTML method getScriptingPartitionType.

private String getScriptingPartitionType(IStructuredDocumentRegion coreNode) {
    String language = null;
    String type = null;
    String result = IHTMLPartitions.SCRIPT;
    IStructuredDocumentRegion node = coreNode;
    ITextRegion attrNameRegion = null;
    while (node != null && isValidScriptingRegionType(node.getType())) {
        node = node.getPrevious();
    }
    ITextRegionList regions = node.getRegions();
    if (regions.size() > 4 && regions.get(1).getType() == DOMRegionContext.XML_TAG_NAME) {
        ITextRegion potentialLanguageRegion = regions.get(1);
        String potentialLanguageString = node.getText(potentialLanguageRegion);
        if (potentialLanguageString.equalsIgnoreCase(HTML40Namespace.ElementName.SCRIPT)) {
            for (int i = 0; i < regions.size(); i++) {
                ITextRegion region = regions.get(i);
                String regionType = region.getType();
                if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)
                    attrNameRegion = region;
                else if (regionType == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
                    String attrName = node.getText(attrNameRegion);
                    if (attrName.equalsIgnoreCase(HTML40Namespace.ATTR_NAME_LANGUAGE))
                        language = StringUtils.strip(node.getText(region));
                    else if (attrName.equalsIgnoreCase(HTML40Namespace.ATTR_NAME_TYPE)) {
                        type = StringUtils.strip(node.getText(region));
                        /*
							 * Avoid partition names built with MIME subtypes,
							 * e.g. type="text/javascript;e4x=1"
							 */
                        if (type != null) {
                            int index = type.indexOf(';');
                            if (index > 1)
                                type = type.substring(0, index);
                        }
                        break;
                    }
                    attrNameRegion = null;
                }
            }
        }
    }
    if (type != null)
        result = lookupScriptType(type);
    else if (language != null)
        result = lookupScriptLanguage(language);
    return result;
}
Also used : ITextRegionList(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList) IStructuredDocumentRegion(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion) ITextRegion(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion)

Example 25 with ITextRegion

use of org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion in project webtools.sourceediting by eclipse.

the class StructuredAutoEditStrategyHTML method getElementName.

/**
 * Get the element name that will be created by closing the start tag. Defaults
 * to the node's nodeName.
 * @param node the node that is being edited
 * @param offset the offset in the document where the start tag is closed
 * @return The element name of the tag
 */
private String getElementName(IDOMNode node, int offset) {
    String name = null;
    IStructuredDocumentRegion region = node.getFirstStructuredDocumentRegion();
    ITextRegion textRegion = region.getRegionAtCharacterOffset(offset);
    if (textRegion != null && textRegion.getType() == DOMRegionContext.XML_TAG_NAME) {
        int nameStart = region.getStartOffset(textRegion);
        String regionText = region.getText(textRegion);
        int length = offset - nameStart;
        if (length <= regionText.length())
            name = regionText.substring(0, length);
    }
    // Default to the node name
    if (name == null)
        name = node.getNodeName();
    return name;
}
Also used : IStructuredDocumentRegion(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion) ITextRegion(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion)

Aggregations

ITextRegion (org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion)447 ITextRegionList (org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList)179 IStructuredDocumentRegion (org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion)174 Iterator (java.util.Iterator)75 IDOMNode (org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode)58 ArrayList (java.util.ArrayList)40 ITextRegionContainer (org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer)39 IndexedRegion (org.eclipse.wst.sse.core.internal.provisional.IndexedRegion)35 IStructuredDocument (org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument)35 List (java.util.List)33 RegionIterator (org.eclipse.wst.css.core.internal.util.RegionIterator)31 BadLocationException (org.eclipse.jface.text.BadLocationException)30 RegionIterator (org.eclipse.wst.dtd.core.internal.text.RegionIterator)22 TextRegionListImpl (org.eclipse.wst.sse.core.internal.text.TextRegionListImpl)19 ITextRegionCollection (org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection)16 Node (org.w3c.dom.Node)16 ContextRegion (org.eclipse.wst.sse.core.internal.parser.ContextRegion)15 IOException (java.io.IOException)13 IRegion (org.eclipse.jface.text.IRegion)13 StyleRange (org.eclipse.swt.custom.StyleRange)13