private void checkSemiColon() {
    fAppendSemiColon = false;

    ITextRegion targetRegion = fContext.getTargetRegion();
    if (targetRegion != null
        && targetRegion.getType() != CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
      // find trailing ":" or ";"
      // if ":" before ";" is found, add ";"
      RegionIterator iterator = fContext.getRegionIterator();
      IStructuredDocumentRegion container = iterator.getStructuredDocumentRegion();
      while (iterator.hasNext()) {
        ITextRegion region = iterator.next();
        if (iterator.getStructuredDocumentRegion() != container) {
          break;
        }
        if (region.getType() == CSSRegionContexts.CSS_DECLARATION_SEPARATOR) {
          fAppendSemiColon = true;
          break;
        }
      }
      if (!fAppendSemiColon) {
        // second chance:
        // leading IStructuredDocumentRegion is not ";"
        IStructuredDocumentRegion nextStructuredDocumentRegion =
            CSSUtil.findNextSignificantNode(container);
        if (CSSUtil.getStructuredDocumentRegionType(nextStructuredDocumentRegion)
            != CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
          fAppendSemiColon = true;
        }
      }
    }
  }
 protected CompoundRegion[] getRegionsWithoutWhiteSpaces(
     IStructuredDocument model, IRegion reg, CSSCleanupStrategy stgy) {
   int start = reg.getOffset();
   int end = reg.getOffset() + reg.getLength() - 1;
   ArrayList list = new ArrayList();
   IStructuredDocumentRegion flatNode = model.getRegionAtCharacterOffset(start);
   while (flatNode != null && flatNode.getStartOffset() <= end) {
     ITextRegionList regionList = flatNode.getRegions();
     Iterator it = regionList.iterator();
     while (it.hasNext()) {
       ITextRegion region = (ITextRegion) it.next();
       if (flatNode.getStartOffset(region) < start) continue;
       if (end < flatNode.getStartOffset(region)) break;
       if (region.getType() != CSSRegionContexts.CSS_S
           || (isCleanup() && !stgy.isFormatSource())) // for
         // not
         // formatting
         // case
         // on
         // cleanup
         // action
         list.add(new CompoundRegion(flatNode, region));
     }
     flatNode = flatNode.getNext();
   }
   if (list.size() > 0) {
     CompoundRegion[] regions = new CompoundRegion[list.size()];
     list.toArray(regions);
     return regions;
   }
   return new CompoundRegion[0];
 }
  /**
   * @return int
   * @param node org.eclipse.wst.css.core.model.interfaces.ICSSNode
   * @param insertPos int
   */
  public int getLengthToReformatAfter(ICSSNode node, int insertPos) {
    if (node == null) return 0;
    IndexedRegion nnode = (IndexedRegion) node;
    if (insertPos < 0 || !nnode.contains(insertPos)) return 0;

    IStructuredDocumentRegion flatNode =
        node.getOwnerDocument()
            .getModel()
            .getStructuredDocument()
            .getRegionAtCharacterOffset(insertPos);
    if (flatNode == null) return 0;
    ITextRegion region = flatNode.getRegionAtCharacterOffset(insertPos);
    if (region == null) return 0;
    RegionIterator it = new RegionIterator(flatNode, region);
    boolean found = false;
    while (it.hasNext()) {
      region = it.next();
      // if (region.getType() != CSSRegionContexts.CSS_S &&
      // region.getType() != CSSRegionContexts.CSS_DELIMITER &&
      // region.getType() !=
      // CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
      if (region.getType() != CSSRegionContexts.CSS_S) {
        found = true;
        break;
      }
    }
    int pos =
        (found
                ? it.getStructuredDocumentRegion().getStartOffset(region)
                : it.getStructuredDocumentRegion().getTextEndOffset(region))
            - insertPos;
    return (pos >= 0) ? pos : 0;
  }
 /** this method has no validation check, then regions must be passed getFunctionName()... */
 private ITextRegionList getFunctionParameters(ITextRegionList regions, String[] accepts) {
   ITextRegionList newRegions = new TextRegionListImpl();
   int nAccepts = (accepts != null) ? accepts.length : 0;
   Iterator i = regions.iterator();
   i.next(); // skip FUNCTION
   while (i.hasNext()) {
     ITextRegion region = (ITextRegion) i.next();
     if (region == null) {
       continue;
     }
     String type = region.getType();
     if (isBlank(type)) {
       continue;
     }
     if (nAccepts == 0) {
       newRegions.add(region);
     } else {
       for (int iAccept = 0; iAccept < nAccepts; iAccept++) {
         if (type == accepts[iAccept]) {
           newRegions.add(region);
           break;
         }
       }
     }
   }
   return newRegions;
 }
 private String getCollapsedText(ITextRegion region) {
   if (fParentRegion == null) return ""; // $NON-NLS-1$
   StringBuffer text = new StringBuffer(fParentRegion.getFullText(region));
   if (region.getLength() > region.getTextLength())
     text.replace(region.getTextLength(), region.getLength(), " "); // $NON-NLS-1$
   return text.toString();
 }
  protected List<IRegion> getAttributeValueRegions(ITextViewer viewer) {
    List<IRegion> regions = new ArrayList<IRegion>();
    IDocument document = viewer.getDocument();
    int startOffset = 0;
    int endOffset = document.getLength();

    IStructuredDocumentRegion sdRegion = null;

    while (startOffset < endOffset
        && (sdRegion = ContentAssistUtils.getStructuredDocumentRegion(viewer, startOffset))
            != null) {
      ITextRegionList list = sdRegion.getRegions();

      for (int i = 0; list != null && i < list.size(); i++) {
        ITextRegion region = list.get(i);
        if (region.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {

          final int regionOffset = sdRegion.getStartOffset() + region.getStart();
          final int regionLength = region.getTextLength();

          regions.add(new Region(regionOffset, regionLength));
        }
      }
      startOffset += sdRegion.getLength();
    }

    return regions;
  }
 private CSSPrimitiveValueImpl createStringValue(ITextRegionList regions) {
   String type = CSSRegionContexts.CSS_DECLARATION_VALUE_IDENT;
   if (regions.size() == 1) {
     ITextRegion region = regions.get(0);
     type = region.getType();
   }
   return createStringValue(makeString(regions), type);
 }
  private CSSPrimitiveValueImpl createRectValue(ITextRegionList regions) {
    String funcName = getFunctionName(regions);
    if (funcName == null || !funcName.toLowerCase().equals("rect")) { // $NON-NLS-1$
      return null;
    }
    String accepts[] = {
      CSSRegionContexts.CSS_DECLARATION_VALUE_NUMBER,
      CSSRegionContexts.CSS_DECLARATION_VALUE_DIMENSION,
      CSSRegionContexts.CSS_DECLARATION_VALUE_IDENT
    }; // IDENT:
    // for
    // 'auto'
    ITextRegionList valueRegions = getFunctionParameters(regions, accepts);
    if (valueRegions.size() != 4) {
      return null;
    }

    RectImpl value = getRect();
    if (value == null) {
      return null;
    }

    for (int i = 0; i < 4; i++) {
      ITextRegion region = valueRegions.get(i);
      CSSPrimitiveValueImpl childValue = null;
      switch (i) {
        case 0:
          childValue = (CSSPrimitiveValueImpl) value.getTop();
          break;
        case 1:
          childValue = (CSSPrimitiveValueImpl) value.getRight();
          break;
        case 2:
          childValue = (CSSPrimitiveValueImpl) value.getBottom();
          break;
        case 3:
          childValue = (CSSPrimitiveValueImpl) value.getLeft();
          break;
        default:
          break;
      }
      if (childValue == null) {
        return null;
      }
      String text = getText(region);
      String type = region.getType();
      if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_IDENT) {
        setStringValue(childValue, text, type);
      } else {
        setFloatValue(childValue, text, type);
      }
      if (!fTempStructuredDocument) {
        childValue.setRangeRegion(fParentRegion, region, region);
      }
    }

    return value;
  }
  public boolean prepareTextRegion(
      ITextRegionCollection blockedRegion,
      int partitionStartOffset,
      int partitionLength,
      Collection<StyleRange> holdResults) {

    boolean handled = false;
    final int partitionEndOffset = partitionStartOffset + partitionLength - 1;
    ITextRegion region = null;
    ITextRegionList regions = blockedRegion.getRegions();
    int nRegions = regions.size();
    StyleRange styleRange = null;
    for (int i = 0; i < nRegions; i++) {
      region = regions.get(i);
      TextAttribute attr = null;
      //            TextAttribute previousAttr = null;
      final int startOffset = blockedRegion.getStartOffset(region);
      if (startOffset > partitionEndOffset) break;
      if (blockedRegion.getEndOffset(region) <= partitionStartOffset) continue;

      if (region instanceof ITextRegionCollection) {
        handled =
            prepareTextRegion(
                (ITextRegionCollection) region, partitionStartOffset, partitionLength, holdResults);
      } else {

        if (region.getType() == TwigRegionContext.TWIG_CONTENT
            || region.getType() == TwigRegionContext.TWIG_COMMENT) {
          handled =
              prepareTwigRegions(
                  holdResults,
                  (ITwigScriptRegion) region,
                  startOffset,
                  partitionStartOffset,
                  partitionLength);
        } else {

          attr = getAttributeFor(region);
          if (attr != null) {
            handled = true;
            styleRange =
                createStyleRange(
                    blockedRegion, region, attr, partitionStartOffset, partitionLength);
            holdResults.add(styleRange);
            // technically speaking, we don't need to update
            // previousAttr
            // in the other case, because the other case is when
            // it hasn't changed
            //                        previousAttr = attr;
          } else {
            //                        previousAttr = null;
          }
        }
      }
    }
    return handled;
  }
  private void addSemiColon(List candidates) {
    ICSSNode targetNode = fContext.getTargetNode();
    if (targetNode instanceof ICSSStyleDeclItem) {
      ICSSNode firstChild = targetNode.getFirstChild();
      if (firstChild == null) {
        return;
      }
      if (firstChild instanceof IndexedRegion) {
        int startOffset = ((IndexedRegion) firstChild).getStartOffset();
        if (fContext.getCursorPos() <= startOffset) {
          return;
        }
      }
    }

    boolean bAddCloser = false;

    ITextRegion targetRegion = fContext.getTargetRegion();
    if (targetRegion != null
        && targetRegion.getType() != CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
      // find trailing ":" or ";"
      // if ":" before ";" is found, add ";"
      RegionIterator iterator = fContext.getRegionIterator();
      IStructuredDocumentRegion container = iterator.getStructuredDocumentRegion();
      while (iterator.hasNext()) {
        ITextRegion region = iterator.next();
        if (iterator.getStructuredDocumentRegion() != container) {
          break;
        }
        if (region.getType() == CSSRegionContexts.CSS_DECLARATION_SEPARATOR) {
          bAddCloser = true;
          break;
        }
      }
      if (!bAddCloser) {
        // second chance:
        // leading IStructuredDocumentRegion is not ";"
        IStructuredDocumentRegion nextStructuredDocumentRegion =
            CSSUtil.findNextSignificantNode(container);
        if (CSSUtil.getStructuredDocumentRegionType(nextStructuredDocumentRegion)
            != CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
          bAddCloser = true;
        }
      }
    }

    if (bAddCloser) {
      CSSCACandidate item = new CSSCACandidate();
      String text = fContext.getTextToReplace() + ";"; // $NON-NLS-1$
      item.setReplacementString(text);
      item.setCursorPosition(text.length());
      item.setDisplayString(";"); // $NON-NLS-1$
      item.setImageType(null);
      candidates.add(item);
    }
  }
示例#11
0
  public Object execute(ExecutionEvent event) throws ExecutionException {
    IEditorPart editor = HandlerUtil.getActiveEditor(event);
    ITextEditor textEditor = null;
    if (editor instanceof ITextEditor) textEditor = (ITextEditor) editor;
    else {
      Object o = editor.getAdapter(ITextEditor.class);
      if (o != null) textEditor = (ITextEditor) o;
    }
    if (textEditor != null) {
      IDocument document =
          textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());

      if (document != null) {
        // get current text selection
        ITextSelection textSelection = getCurrentSelection(textEditor);

        // If there is alternating or more then one block in the text
        // selection, action is aborted !
        if (isMoreThanOneContextBlockSelected(document, textSelection)) {
          // displayCommentActinosErrorDialog(editor);
          // return null;
          org.eclipse.wst.sse.ui.internal.handlers.AddBlockCommentHandler
              addBlockCommentHandlerWST =
                  new org.eclipse.wst.sse.ui.internal.handlers
                      .AddBlockCommentHandler(); // org.eclipse.wst.sse.ui.internal.handlers.AddBlockCommentHandler();
          return addBlockCommentHandlerWST.execute(event);
        }

        if (textSelection.isEmpty()) {
          return null;
        }
        if (document instanceof IStructuredDocument) {
          int selectionOffset = textSelection.getOffset();
          IStructuredDocument sDoc = (IStructuredDocument) document;
          IStructuredDocumentRegion sdRegion = sDoc.getRegionAtCharacterOffset(selectionOffset);
          ITextRegion textRegion = sdRegion.getRegionAtCharacterOffset(selectionOffset);

          ITextRegionCollection container = sdRegion;

          if (textRegion instanceof ITextRegionContainer) {
            container = (ITextRegionContainer) textRegion;
            textRegion = container.getRegionAtCharacterOffset(selectionOffset);
          }
          if (textRegion.getType() == PHPRegionContext.PHP_CONTENT) {
            processAction(textEditor, document, textSelection);
          } else {
            org.eclipse.wst.sse.ui.internal.handlers.AddBlockCommentHandler
                addBlockCommentHandlerWST =
                    new org.eclipse.wst.sse.ui.internal.handlers.AddBlockCommentHandler();
            return addBlockCommentHandlerWST.execute(event);
          }
        }
      }
    }
    return null;
  }
 private String getFunctionName(ITextRegionList regions) {
   if (regions == null || regions.size() < 2) {
     return null;
   }
   ITextRegion firstRegion = regions.get(0);
   if (firstRegion.getType() != CSSRegionContexts.CSS_DECLARATION_VALUE_FUNCTION) {
     return null;
   }
   ITextRegion lastRegion = regions.get(regions.size() - 1);
   if (lastRegion.getType() != CSSRegionContexts.CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE) {
     return null;
   }
   String text = getText(firstRegion);
   return text.substring(0, text.length() - 1);
 }
  private CSSPrimitiveValueImpl createPrimitiveValue(ITextRegion region, String propertyValue) {
    if (region == null) {
      return null;
    }
    CSSPrimitiveValueImpl value = null;
    String type = region.getType();
    String text = propertyValue != null ? propertyValue : getText(region);
    if (isBlank(type)) {
      value = null;
    } else if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_NUMBER
        || type == CSSRegionContexts.CSS_DECLARATION_VALUE_DIMENSION
        || type == CSSRegionContexts.CSS_DECLARATION_VALUE_PERCENTAGE) {
      value = createFloatValue(text, type);
    } else if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_STRING
        || type == CSSRegionContexts.CSS_DECLARATION_VALUE_URI
        || type == CSSRegionContexts.CSS_DECLARATION_VALUE_IDENT
        || type == CSSRegionContexts.CSS_DECLARATION_VALUE_HASH) {
      value = createStringValue(text, type);
    }

    if (value == null) {
      value = createStringValue(text, type);
    }

    if (!fTempStructuredDocument && value != null) {
      value.setRangeRegion(fParentRegion, region, region);
    }

    return value;
  }
  @Override
  protected ContentAssistRequest computeCompletionProposals(
      String matchString,
      ITextRegion completionRegion,
      IDOMNode treeNode,
      IDOMNode xmlnode,
      CompletionProposalInvocationContext context) {
    ContentAssistRequest contentAssistRequest =
        super.computeCompletionProposals(matchString, completionRegion, treeNode, xmlnode, context);
    if (contentAssistRequest != null) return contentAssistRequest;

    String regionType = completionRegion.getType();
    if (DOMRegionContext.XML_CDATA_TEXT.equals(regionType)) {
      Node parentNode = xmlnode.getParentNode();
      Node statementNode = MybatipseXmlUtil.findEnclosingStatementNode(parentNode);
      if (statementNode == null) return null;

      int offset = context.getInvocationOffset();
      ITextViewer viewer = context.getViewer();
      contentAssistRequest =
          new ContentAssistRequest(
              xmlnode,
              parentNode,
              ContentAssistUtils.getStructuredDocumentRegion(viewer, offset),
              completionRegion,
              offset,
              0,
              matchString);
      proposeStatementText(contentAssistRequest, statementNode);
    }
    return contentAssistRequest;
  }
  /**
   * Returns a pair of (tag-balance,bracket-balance) for the range textStart to offset.
   *
   * @param doc the document
   * @param start the offset of the starting character (inclusive)
   * @param end the offset of the ending character (exclusive)
   * @return the balance of tags and brackets
   */
  private static Pair<Integer, Integer> getBalance(IStructuredDocument doc, int start, int end) {
    // Balance of open and closing tags
    // <foo></foo> has tagBalance = 0, <foo> has tagBalance = 1
    int tagBalance = 0;
    // Balance of open and closing brackets
    // <foo attr1="value1"> has bracketBalance = 1, <foo has bracketBalance = 1
    int bracketBalance = 0;
    IStructuredDocumentRegion region = doc.getRegionAtCharacterOffset(start);

    if (region != null) {
      boolean inOpenTag = true;
      while (region != null && region.getStartOffset() < end) {
        int regionStart = region.getStartOffset();
        ITextRegionList subRegions = region.getRegions();
        for (int i = 0, n = subRegions.size(); i < n; i++) {
          ITextRegion subRegion = subRegions.get(i);
          int subRegionStart = regionStart + subRegion.getStart();
          int subRegionEnd = regionStart + subRegion.getEnd();
          if (subRegionEnd < start || subRegionStart >= end) {
            continue;
          }
          String type = subRegion.getType();

          if (XML_TAG_OPEN.equals(type)) {
            bracketBalance++;
            inOpenTag = true;
          } else if (XML_TAG_CLOSE.equals(type)) {
            bracketBalance--;
            if (inOpenTag) {
              tagBalance++;
            } else {
              tagBalance--;
            }
          } else if (XML_END_TAG_OPEN.equals(type)) {
            bracketBalance++;
            inOpenTag = false;
          } else if (XML_EMPTY_TAG_CLOSE.equals(type)) {
            bracketBalance--;
          }
        }

        region = region.getNext();
      }
    }

    return Pair.of(tagBalance, bracketBalance);
  }
  private CSSPrimitiveValueImpl createRgbValue(ITextRegionList regions) {
    String funcName = getFunctionName(regions);
    if (funcName == null || !funcName.toLowerCase().equals("rgb")) { // $NON-NLS-1$
      return null;
    }
    String accepts[] = {
      CSSRegionContexts.CSS_DECLARATION_VALUE_NUMBER,
      CSSRegionContexts.CSS_DECLARATION_VALUE_PERCENTAGE
    };
    ITextRegionList valueRegions = getFunctionParameters(regions, accepts);
    if (valueRegions.size() != 3) {
      return null;
    }

    RGBColorImpl value = getRGBColor();
    if (value == null) {
      return null;
    }

    for (int i = 0; i < 3; i++) {
      ITextRegion region = valueRegions.get(i);
      CSSPrimitiveValueImpl childValue = null;
      switch (i) {
        case 0:
          childValue = (CSSPrimitiveValueImpl) value.getRed();
          break;
        case 1:
          childValue = (CSSPrimitiveValueImpl) value.getGreen();
          break;
        case 2:
          childValue = (CSSPrimitiveValueImpl) value.getBlue();
          break;
        default:
          break;
      }
      if (childValue == null) {
        return null;
      }
      setFloatValue(childValue, getText(region), region.getType());
      if (!fTempStructuredDocument) {
        childValue.setRangeRegion(fParentRegion, region, region);
      }
    }

    return value;
  }
  protected int getLength(ITextRegion valueRegion, boolean isMissingEndQuote) {
    int length = valueRegion.getLength();

    if (isMissingEndQuote) {
      return length - 1;
    } else {
      return length - 2;
    }
  }
  private String makeString(ITextRegionList regions) {
    StringBuffer buf = new StringBuffer();
    boolean bSpace = false;
    for (Iterator i = regions.iterator(); i.hasNext(); ) {
      ITextRegion region = (ITextRegion) i.next();
      String type = region.getType();
      if (!bSpace && isBlank(type)) {
        buf.append(" "); // $NON-NLS-1$
        bSpace = true;
      } else {
        // [274945] Multiple regions should have the spaces between collapsed
        String text = i.hasNext() ? getCollapsedText(region) : getText(region);
        buf.append(text);
        bSpace = false;
      }
    }

    return buf.toString();
  }
 private String getPropertyName(ITextRegionList nodeRegions) {
   ITextRegionList nameRegions = new TextRegionListImpl();
   String name = null;
   while (!nodeRegions.isEmpty()) {
     ITextRegion region = nodeRegions.remove(0);
     if (region == null) {
       continue;
     }
     String type = region.getType();
     if (type == CSSRegionContexts.CSS_DECLARATION_SEPARATOR) {
       CSSUtil.stripSurroundingSpace(nameRegions);
       name = makeString(nameRegions);
       break;
     } else {
       nameRegions.add(region);
     }
   }
   return name;
 }
  @Override
  public TextAttribute getAttributeFor(ITextRegion region) {

    final String type = region.getType();

    if (type != null && type.startsWith("TWIG_")) {
      return getAttributeFor(type);
    }

    return super.getAttributeFor(region);
  }
  private CSSPrimitiveValueImpl createPrimitiveValue(ITextRegionList regions) {
    CSSPrimitiveValueImpl value = null;
    CSSUtil.stripSurroundingSpace(regions);
    if (regions.isEmpty()) {
      return null;
    }
    ITextRegion region = regions.get(0);
    if (region == null) {
      return null;
    }
    String type = region.getType();
    if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_FUNCTION) {
      String text = getText(region).toLowerCase();
      if (text.equals("rgb(")) { // $NON-NLS-1$
        value = createRgbValue(regions);
      } else if (text.equals("counter(")) { // $NON-NLS-1$
        value = createCounterValue(regions);
      } else if (text.equals("counters(")) { // $NON-NLS-1$
        value = createCountersValue(regions);
      } else if (text.equals("attr(")) { // $NON-NLS-1$
        value = createAttrValue(regions);
      } else if (text.equals("format(")) { // $NON-NLS-1$
        value = createFormatValue(regions);
      } else if (text.equals("local(")) { // $NON-NLS-1$
        value = createLocalValue(regions);
      } else if (text.equals("rect(")) { // $NON-NLS-1$
        value = createRectValue(regions);
      }
      if (value == null) {
        value = createStringValue(regions);
      }
    } else {
      value = createStringValue(regions);
    }

    if (!fTempStructuredDocument && value != null) {
      value.setRangeRegion(fParentRegion, regions.get(0), regions.get(regions.size() - 1));
    }

    return value;
  }
  public static boolean hasColonSeparator(IStructuredDocumentRegion flatNode) {
    if (flatNode == null) {
      return false;
    }
    ITextRegionList regions = flatNode.getRegions();
    if (regions == null || regions.size() == 0) {
      return false;
    }

    for (Iterator i = regions.iterator(); i.hasNext(); ) {
      ITextRegion region = (ITextRegion) i.next();
      if (region == null) {
        continue;
      }
      if (region.getType() == CSSRegionContexts.CSS_DECLARATION_SEPARATOR) {
        return true;
      }
    }

    return false;
  }
  protected CompoundRegion[] getRegions(
      IStructuredDocument model, IRegion reg, IRegion exceptFor, String pickupType) {
    int start = reg.getOffset();
    int end = reg.getOffset() + reg.getLength();
    int startE = (exceptFor != null) ? exceptFor.getOffset() : -1;
    int endE = (exceptFor != null) ? exceptFor.getOffset() + exceptFor.getLength() : 0;

    ArrayList list = new ArrayList();
    IStructuredDocumentRegion flatNode = model.getRegionAtCharacterOffset(start);
    boolean pickuped = false;
    while (flatNode != null && flatNode.getStartOffset() < end) {
      ITextRegionList regionList = flatNode.getRegions();
      Iterator it = regionList.iterator();
      while (it.hasNext()) {
        ITextRegion region = (ITextRegion) it.next();
        if (flatNode.getStartOffset(region) < start) continue;
        if (end <= flatNode.getStartOffset(region)) break;
        if (startE >= 0
            && startE <= flatNode.getStartOffset(region)
            && flatNode.getEndOffset(region) <= endE) continue;
        if (region.getType() == CSSRegionContexts.CSS_COMMENT
            || region.getType() == CSSRegionContexts.CSS_CDC
            || region.getType() == CSSRegionContexts.CSS_CDO)
          list.add(new CompoundRegion(flatNode, region));
        else if (!pickuped && region.getType() == pickupType) {
          list.add(new CompoundRegion(flatNode, region));
          pickuped = true;
        }
      }
      flatNode = flatNode.getNext();
    }
    if (list.size() > 0) {
      CompoundRegion[] regions = new CompoundRegion[list.size()];
      list.toArray(regions);
      return regions;
    }
    return new CompoundRegion[0];
  }
 public int getPrefixEnd() throws BadLocationException {
   ITextRegion phpToken = getPHPToken();
   if (phpToken.getType() == PHPRegionTypes.PHP_NS_SEPARATOR
       // Check that there's no other (whitespace) characters
       // after the namespace separator, otherwise there's no reason
       // to retrieve the next region.
       && phpToken.getLength() == NamespaceReference.NAMESPACE_DELIMITER.length()) {
     IPhpScriptRegion phpScriptRegion = getPhpScriptRegion();
     ITextRegion nextRegion = phpScriptRegion.getPhpToken(phpToken.getEnd());
     // Also check that we only retrieve PHP labels.
     if (nextRegion.getType() == PHPRegionTypes.PHP_LABEL) {
       return getRegionCollection().getStartOffset()
           + phpScriptRegion.getStart()
           + nextRegion.getTextEnd();
     }
   }
   return super.getPrefixEnd();
 }
  protected void addAttributeValueProposals(
      ContentAssistRequest contentAssistRequest, CompletionProposalInvocationContext context) {
    IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
    String tagName = node.getNodeName();
    IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
    ITextRegionList openRegions = open.getRegions();
    int i = openRegions.indexOf(contentAssistRequest.getRegion());
    if (i < 0) return;
    ITextRegion nameRegion = null;
    while (i >= 0) {
      nameRegion = openRegions.get(i--);
      if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) break;
    }

    // get the attribute in question (first attr name to the left of the cursor)
    String attributeName = null;
    if (nameRegion != null) attributeName = open.getText(nameRegion);

    ProposalType proposalType = resolveProposalType(tagName, attributeName);
    if (ProposalType.None.equals(proposalType)) {
      return;
    }

    String currentValue = null;
    if (contentAssistRequest.getRegion().getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
      currentValue = contentAssistRequest.getText();
    else currentValue = "";

    String matchString = null;
    int matchStrLen = contentAssistRequest.getMatchString().length();
    int start = contentAssistRequest.getReplacementBeginPosition();
    int length = contentAssistRequest.getReplacementLength();
    if (currentValue.length() > StringUtils.strip(currentValue).length()
        && (currentValue.startsWith("\"") || currentValue.startsWith("'"))
        && matchStrLen > 0) {
      // Value is surrounded by (double) quotes.
      matchString = currentValue.substring(1, matchStrLen);
      start++;
      length = currentValue.length() - 2;
      currentValue = currentValue.substring(1, length + 1);
    } else {
      matchString = currentValue.substring(0, matchStrLen);
    }

    IJavaProject project = getJavaProject(contentAssistRequest);
    try {
      switch (proposalType) {
        case Package:
          proposePackage(contentAssistRequest, project, matchString, start, length);
          break;
        case TypeAlias:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeJavaType(project, start, length, false, matchString));
          break;
        case ResultType:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeJavaType(project, start, length, true, matchString));
          break;
        case ResultProperty:
          proposeProperty(contentAssistRequest, matchString, start, length, node);
          break;
        case TypeHandlerType:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeTypeHandler(project, start, length, matchString));
          break;
        case CacheType:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeCacheType(project, start, length, matchString));
          break;
        case SettingName:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeSettingName(start, length, matchString));
          break;
        case ObjectFactory:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeObjectFactory(project, start, length, matchString));
          break;
        case ObjectWrapperFactory:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeObjectWrapperFactory(
                  project, start, length, matchString));
          break;
        case StatementId:
          proposeStatementId(contentAssistRequest, project, matchString, start, length, node);
          break;
        case MapperNamespace:
          proposeMapperNamespace(contentAssistRequest, project, start, length);
          break;
        case ResultMap:
          String ownId =
              "resultMap".equals(tagName) && "extends".equals(attributeName)
                  ? XpathUtil.xpathString(node, "@id")
                  : null;
          addProposals(
              contentAssistRequest,
              proposeResultMapReference(
                  project,
                  node.getOwnerDocument(),
                  start,
                  currentValue,
                  matchString.length(),
                  ownId));
          break;
        case Include:
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeReference(
                  project, node.getOwnerDocument(), matchString, start, length, "sql", null));
          break;
        case SelectId:
          // TODO: include mapper methods with @Select.
          addProposals(
              contentAssistRequest,
              ProposalComputorHelper.proposeReference(
                  project, node.getOwnerDocument(), matchString, start, length, "select", null));
          break;
        case KeyProperty:
          String nodeName = node.getNodeName();
          Node statementNode =
              "update".equals(nodeName) || "insert".equals(nodeName)
                  ? node
                  : MybatipseXmlUtil.findEnclosingStatementNode(node.getParentNode());
          addProposals(
              contentAssistRequest,
              proposeParameter(project, start, length, statementNode, false, matchString));
          break;
        case ParamProperty:
          addProposals(
              contentAssistRequest,
              proposeParameter(
                  project,
                  start,
                  length,
                  MybatipseXmlUtil.findEnclosingStatementNode(node),
                  true,
                  matchString));
          break;
        case ParamPropertyPartial:
          AttrTextParser parser = new AttrTextParser(currentValue, matchString.length());
          addProposals(
              contentAssistRequest,
              proposeParameter(
                  project,
                  start + parser.getMatchStringStart(),
                  parser.getReplacementLength(),
                  MybatipseXmlUtil.findEnclosingStatementNode(node.getParentNode()),
                  true,
                  parser.getMatchString()));
          break;
        default:
          break;
      }
    } catch (Exception e) {
      Activator.log(Status.ERROR, e.getMessage(), e);
    }
  }
  /** nodeRegions must be broken. If you need after, make copy of them. */
  private void setupValues(
      ICSSStyleDeclItem item, ITextRegionList nodeRegions, List propertyValueList) {
    if (item == null) {
      return;
    }

    ICSSPrimitiveValue value;
    ITextRegionList regionBuf = new TextRegionListImpl();

    String propertyName = item.getPropertyName().toLowerCase();
    boolean bFont = (propertyName.equals(PropCMProperty.P_FONT));
    // (short-hand) font
    String propertyValue = null;
    int status =
        (propertyName.equals(PropCMProperty.P_VOICE_FAMILY)
                || propertyName.equals(PropCMProperty.P_FONT_FAMILY))
            ? S_COMMA_SEPARATION
            : S_NORMAL;
    while (!nodeRegions.isEmpty()) {
      value = null;
      ITextRegion region = nodeRegions.remove(0);
      if (region == null) {
        continue;
      }
      if (propertyValueList != null && !propertyValueList.isEmpty()) {
        propertyValue = (String) propertyValueList.remove(0);
      }
      String type = region.getType();
      // if (type == CSSRegionContexts.CSS_DECLARATION_DELIMITER || type
      // == CSSRegionContexts.CSS_RBRACE) {
      // break;
      // }
      switch (status) {
        case S_NORMAL:
          if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_FUNCTION) {
            regionBuf.add(region);
            status = S_FUNCTION;
          } else if (bFont
              && type == CSSRegionContexts.CSS_DECLARATION_VALUE_OPERATOR
              && fParentRegion.getText(region).equals("/")) { // $NON-NLS-1$
            value = createPrimitiveValue(region, propertyValue);
            status = S_FONT_SLASH;
          } else if (!isBlank(type)) {
            value = createPrimitiveValue(region, propertyValue);
          }
          break;
        case S_FUNCTION:
          if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE) {
            regionBuf.add(region);
            value = createPrimitiveValue(regionBuf);
            regionBuf.clear();
            status = S_NORMAL;
          } else if (!isBlank(type)) {
            regionBuf.add(region);
          }
          break;
        case S_FONT_SLASH:
          if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_DIMENSION) {
            value = createPrimitiveValue(region, propertyValue);
            status = S_COMMA_SEPARATION;
          } else if (!isBlank(type)) {
            value = createPrimitiveValue(region, propertyValue);
          }
          break;
        case S_COMMA_SEPARATION:
          if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_OPERATOR
              && fParentRegion.getText(region).equals(",")) { // $NON-NLS-1$
            value = createPrimitiveValue(regionBuf);
            regionBuf.clear();
            if (value != null) {
              if (fUpdateContext == null || !fUpdateContext.isActive()) {
                item.appendValue(value);
              }
            }
            value = createPrimitiveValue(region, propertyValue);
          } else {
            regionBuf.add(region);
          }
          break;
        default:
          break;
      }
      if (value != null) {
        if (fUpdateContext == null || !fUpdateContext.isActive()) {
          item.appendValue(value);
        }
      }
    }
    if (!regionBuf.isEmpty()) {
      value = createPrimitiveValue(regionBuf);
      if (fUpdateContext == null || !fUpdateContext.isActive()) {
        item.appendValue(value);
      }
    }
  }
  protected void appendSpaceBefore(ICSSNode node, CompoundRegion toAppend, StringBuffer source) {
    if (node == null || toAppend == null || source == null) return;
    if (isCleanup() && !getCleanupStrategy(node).isFormatSource())
      return; // for not formatting case on cleanup action
    String type = toAppend.getType();

    Preferences preferences = CSSCorePlugin.getDefault().getPluginPreferences();

    boolean needIndent = !(node instanceof ICSSStyleSheet);
    if (type == CSSRegionContexts.CSS_COMMENT) {
      // check whether previous region is 'S' and has CR-LF
      String delim = getLineDelimiter(node);
      RegionIterator it =
          new RegionIterator(toAppend.getDocumentRegion(), toAppend.getTextRegion());
      it.prev();
      ITextRegion prev = it.prev();
      // bug390904
      if (prev.getType() == CSSRegionContexts.CSS_LBRACE
          && TextUtilities.indexOf(
                  DefaultLineTracker.DELIMITERS,
                  it.getStructuredDocumentRegion().getFullText(prev),
                  0)[0]
              > 0) {
        source.append(delim);
        source.append(getIndent(node));
        source.append(getIndentString());
      } else if (prev.getType() == CSSRegionContexts.CSS_S
          && TextUtilities.indexOf(
                  DefaultLineTracker.DELIMITERS, it.getStructuredDocumentRegion().getText(prev), 0)[
                  0]
              >= 0) {
        source.append(delim);
        source.append(getIndent(node));
        if (needIndent) source.append(getIndentString());
      } else {
        appendSpaceBefore(node, toAppend.getText(), source);
      }
    } else if (type == CSSRegionContexts.CSS_LBRACE
        && preferences.getBoolean(CSSCorePreferenceNames.WRAPPING_NEWLINE_ON_OPEN_BRACE)) {
      String delim = getLineDelimiter(node);
      source.append(delim);
      source.append(getIndent(node));
      // } else if (type == CSSRegionContexts.CSS_CURLY_BRACE_CLOSE) {
      // } else if (type == CSSRegionContexts.CSS_INCLUDES || type ==
      // CSSRegionContexts.CSS_DASHMATCH) {
    } else if (type == CSSRegionContexts.CSS_DECLARATION_SEPARATOR
        && node instanceof ICSSStyleDeclItem) {
      int n = preferences.getInt(CSSCorePreferenceNames.FORMAT_PROP_PRE_DELIM);
      // no delimiter case
      while (n-- > 0) source.append(" "); // $NON-NLS-1$
    } else if (type == CSSRegionContexts.CSS_DECLARATION_VALUE_OPERATOR
        || type == CSSRegionContexts.CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE) {
      if (preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH) > 0
          && (!preferences.getBoolean(CSSCorePreferenceNames.WRAPPING_PROHIBIT_WRAP_ON_ATTR)
              || node.getOwnerDocument().getNodeType() != ICSSNode.STYLEDECLARATION_NODE)) {
        int length = getLastLineLength(node, source);
        int append = 1;
        if (length + append > preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH)) {
          source.append(getLineDelimiter(node));
          source.append(getIndent(node));
          if (needIndent) source.append(getIndentString());
        }
      }
    } else if (CSSRegionContexts.CSS_FOREIGN_ELEMENT == type
        || CSSRegionContexts.CSS_DECLARATION_DELIMITER == type) {
      return;
    } else appendSpaceBefore(node, toAppend.getText(), source);
  }
  protected void appendDelimBefore(ICSSNode node, CompoundRegion toAppend, StringBuffer source) {
    if (node == null || source == null) return;
    if (isCleanup() && !getCleanupStrategy(node).isFormatSource())
      return; // for not formatting case on cleanup action
    String delim = getLineDelimiter(node);

    boolean needIndent = !(node instanceof ICSSStyleSheet);
    if (toAppend == null) {
      source.append(delim);
      source.append(getIndent(node));
      if (needIndent) source.append(getIndentString());
    } else {
      String type = toAppend.getType();
      if (type == CSSRegionContexts.CSS_COMMENT) {
        RegionIterator it =
            new RegionIterator(toAppend.getDocumentRegion(), toAppend.getTextRegion());
        it.prev();
        ITextRegion prev = it.prev();
        int[] result = null;
        if (prev == null
            || (prev.getType() == CSSRegionContexts.CSS_S
                && (result =
                            TextUtilities.indexOf(
                                DefaultLineTracker.DELIMITERS,
                                it.getStructuredDocumentRegion().getText(prev),
                                0))
                        [0]
                    >= 0)) {
          // Collapse to one empty line if there's more than one.
          int offset = result[0] + DefaultLineTracker.DELIMITERS[result[1]].length();
          if (offset < it.getStructuredDocumentRegion().getText(prev).length()) {
            if (TextUtilities.indexOf(
                    DefaultLineTracker.DELIMITERS,
                    it.getStructuredDocumentRegion().getText(prev),
                    offset)[0]
                >= 0) {
              source.append(delim);
            }
          }
          source.append(delim);
          source.append(getIndent(node));
          if (needIndent) source.append(getIndentString());
        } else if (prev.getType() == CSSRegionContexts.CSS_COMMENT) {
          String fullText = toAppend.getDocumentRegion().getFullText(prev);
          String trimmedText = toAppend.getDocumentRegion().getText(prev);
          String whiteSpaces = ""; // $NON-NLS-1$
          if (fullText != null && trimmedText != null)
            whiteSpaces = fullText.substring(trimmedText.length());
          int[] delimiterFound =
              TextUtilities.indexOf(DefaultLineTracker.DELIMITERS, whiteSpaces, 0);
          if (delimiterFound[0] != -1) {
            source.append(delim);
          } else {
            appendSpaceBefore(node, toAppend.getText(), source);

            /*If two comments can't be adjusted in one line(combined length exceeds line width),
             * a tab is also appended along with next line delimiter , we need to remove that.
             */
            if (source.toString().endsWith(getIndentString())) {
              source.delete((source.length() - getIndentString().length()), source.length());
            }
          }
        } else {
          appendSpaceBefore(node, toAppend.getText(), source);
        }
      } else if (type == CSSRegionContexts.CSS_DELIMITER
          || type == CSSRegionContexts.CSS_DECLARATION_DELIMITER) {
        RegionIterator it =
            new RegionIterator(toAppend.getDocumentRegion(), toAppend.getTextRegion());
        it.prev();
        ITextRegion prev = it.prev();

        Preferences preferences = CSSCorePlugin.getDefault().getPluginPreferences();

        if (prev.getType() == CSSRegionContexts.CSS_S
            && TextUtilities.indexOf(
                    DefaultLineTracker.DELIMITERS,
                    it.getStructuredDocumentRegion().getText(prev),
                    0)[0]
                >= 0) {
          source.append(delim);
          source.append(getIndent(node));
          if (needIndent) source.append(getIndentString());
        } else if (preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH) > 0
            && (!preferences.getBoolean(CSSCorePreferenceNames.WRAPPING_PROHIBIT_WRAP_ON_ATTR)
                || node.getOwnerDocument().getNodeType() != ICSSNode.STYLEDECLARATION_NODE)) {
          int length = getLastLineLength(node, source);
          int append = 1;
          if (length + append > preferences.getInt(CSSCorePreferenceNames.LINE_WIDTH)) {
            source.append(getLineDelimiter(node));
            source.append(getIndent(node));
            if (needIndent) source.append(getIndentString());
          }
        }
      } else if (type == CSSRegionContexts.CSS_RBRACE || type == CSSRegionContexts.CSS_LBRACE) {
        source.append(delim);
        source.append(getIndent(node));
      } else {
        source.append(delim);
        source.append(getIndent(node));
        if (needIndent) source.append(getIndentString());
      }
    }
  }
  private boolean prepareTwigRegions(
      Collection<StyleRange> holdResults,
      ITwigScriptRegion region,
      int regionStart,
      int partitionStartOffset,
      int partitionLength) {

    assert (region.getType() == TwigRegionContext.TWIG_CONTENT
        || region.getType() == TwigRegionContext.TWIG_COMMENT);

    StyleRange styleRange = null;
    TextAttribute attr;
    TextAttribute previousAttr = null;

    ITextRegion[] twigTokens = null;
    try {

      int from;
      int length;
      if (partitionStartOffset < regionStart) {
        from = 0;
        length = partitionLength - (regionStart - partitionStartOffset);
      } else {
        from = partitionStartOffset - regionStart;
        length = partitionLength;
      }
      twigTokens = region.getTwigTokens(from, Math.min(length, region.getLength()));
      ITextRegion prevElement = null;
      for (int i = 0; i < twigTokens.length; i++) {

        ITextRegion element = twigTokens[i];
        attr = getAttributeFor(element);
        // Check that the elements are different - otherwise the
        // coloring is not valid
        if (prevElement == element || attr == null) {
          continue;
        }
        if ((styleRange != null)
            && (previousAttr != null)
            && (previousAttr.equals(attr))
            && prevElement != null
            && prevElement.getLength() == prevElement.getLength()) {
          // extends the prev styleRange with the current element
          // length
          styleRange.length += element.getLength();
          if (styleRange.start + styleRange.length > partitionStartOffset + partitionLength) {
            styleRange.length -=
                (styleRange.start + styleRange.length) - (partitionStartOffset + partitionLength);
          }
        } else {
          // create new styleRange
          int styleStart = regionStart + element.getStart();
          int styleLength = element.getLength();
          if (styleStart + styleLength < partitionStartOffset) { // if
            // the
            // range
            // ends
            // before
            // the
            // requested
            // starting
            // position
            // -
            // ignoring
            // it
            continue;
          }
          if (styleStart < partitionStartOffset) { // if the region
            // starts before
            // the requested
            // starting
            // position -
            // adjusting the
            // style start
            // position
            styleLength -= (partitionStartOffset - styleStart);
            styleStart = partitionStartOffset;
          }
          if (styleStart > partitionStartOffset + partitionLength) {
            // if the region ends after the requested end position -
            // making it shorter
            styleLength -= styleStart - (partitionStartOffset + partitionLength);
          }
          if (attr.getBackground() != null && element.getTextEnd() != element.getEnd()) { // in
            // case
            // of
            // background
            // color
            // make
            // sure
            // the
            // highlighting
            // will
            // not
            // paint
            // the
            // whitespaces
            // applying style to the region w/o the whitespace
            styleRange =
                new StyleRange(
                    styleStart,
                    styleLength - (element.getEnd() - element.getTextEnd()),
                    attr.getForeground(),
                    attr.getBackground(),
                    attr.getStyle());
            if ((attr.getStyle() & TextAttribute.UNDERLINE) != 0) {
              styleRange.underline = true;
              styleRange.fontStyle &= ~TextAttribute.UNDERLINE;
            }
            if ((attr.getStyle() & TextAttribute.STRIKETHROUGH) != 0) {
              styleRange.strikeout = true;
              styleRange.fontStyle &= ~TextAttribute.STRIKETHROUGH;
            }
            holdResults.add(styleRange);
            // applying style to the whitespace (important for the
            // refresh of the specific range
            styleRange =
                new StyleRange(
                    regionStart + element.getTextEnd(),
                    element.getEnd() - element.getTextEnd(),
                    attr.getForeground(),
                    null,
                    attr.getStyle());
            holdResults.add(styleRange);
            previousAttr = null;
          } else {
            styleRange =
                new StyleRange(
                    styleStart,
                    styleLength,
                    attr.getForeground(),
                    attr.getBackground(),
                    attr.getStyle());
            if ((attr.getStyle() & TextAttribute.UNDERLINE) != 0) {
              styleRange.underline = true;
              styleRange.fontStyle &= ~TextAttribute.UNDERLINE;
            }
            if ((attr.getStyle() & TextAttribute.STRIKETHROUGH) != 0) {
              styleRange.strikeout = true;
              styleRange.fontStyle &= ~TextAttribute.STRIKETHROUGH;
            }
            holdResults.add(styleRange);
            // technically speaking, we don't need to update
            // previousAttr
            // in the other case, because the other case is when
            // it hasn't changed
            previousAttr = attr;
          }
        }
        prevElement = element;
      }
      return true;
    } catch (BadLocationException e) {
      Logger.logException(e);
      return false;
    }
  }
  /*
   * Search the RegionContainer's regions looking for JSP content. If valid
   * content is found, return the position >= 0 If no valid content is
   * found, return NO_VALID_CONTENT. If a region starts after the line's
   * endOffset, return END_OF_LINE.
   */
  private static int getValidRegionPosition(
      IStructuredModel model,
      ITextRegionCollection regionContainer,
      int startOffset,
      int endOffset) {

    ITextRegionList regions = regionContainer.getRegions();
    for (int i = 0; i < regions.size(); i++) {
      ITextRegion region = regions.get(i);
      if (region instanceof ITextRegionCollection) {
        int validPosition =
            getValidRegionPosition(model, (ITextRegionCollection) region, startOffset, endOffset);
        if (validPosition == END_OF_LINE || validPosition >= 0) return validPosition;
      } else {
        // region must be at least partially on selected line
        if (regionContainer.getEndOffset(region) > startOffset) {

          int regionStartOffset = regionContainer.getStartOffset(region);
          // if region starts after line's endOffset, we're done
          // searching
          if (regionStartOffset > endOffset) return END_OF_LINE;

          // If region is JSP content, make sure the language is
          // Java not Javascript by
          // checking the content assist adapter's type.
          if (region.getType().equals(DOMJSPRegionContexts.JSP_CONTENT)) {
            // DWM: this logic is not incorrect ... given changes
            // to adapters, etc.
            // but probably don't need anything here, since both
            // Java and JavaScript
            // are supported in V5.

            // nsd_TODO: verify this!!!

            // INodeNotifier notifier =
            // (INodeNotifier)model.getNode(region.getStartOffset());
            // IAdapterFactory factory =
            // model.getFactoryRegistry().getFactoryFor(ContentAssistAdapter.class);
            // if(factory instanceof
            // HTMLContentAssistAdapterFactory) {
            // INodeAdapter adapter =
            // ((HTMLContentAssistAdapterFactory)factory).createAdapter(notifier,
            // region);
            // if(adapter != null && adapter instanceof
            // JSPJavaContentAssistAdapter)

            if (regionStartOffset > startOffset) return regionStartOffset;
            else return startOffset;
            // }
          }
          // a custom tag, jsp:useBean, getproperty or setproperty
          // statement is also a valid breakpoint location
          else if (region.getType().equals(DOMRegionContext.XML_TAG_NAME)
              && (isCustomTagRegion(model.getIndexedRegion(regionStartOffset))
                  || regionContainer.getText(region).equals(JSP12Namespace.ElementName.USEBEAN)
                  || regionContainer.getText(region).equals(JSP12Namespace.ElementName.GETPROPERTY)
                  || regionContainer
                      .getText(region)
                      .equals(JSP12Namespace.ElementName.SETPROPERTY))) {

            if (regionStartOffset > startOffset) return regionStartOffset;
            else return startOffset;
          } else {
            // Defect #241090, the Text Nodes inside of JSP
            // scriptlets, expressions, and declarations are valid
            // breakpoint-able locations
            boolean isCodeNode = false;
            IndexedRegion node = model.getIndexedRegion(regionStartOffset);
            if (node != null && node instanceof Node) {
              Node domNode = (Node) node;
              Node root = domNode.getOwnerDocument().getDocumentElement();
              if (root != null
                  && root.getNodeName().equals(JSP12Namespace.ElementName.ROOT)
                  && domNode.getNodeType() == Node.TEXT_NODE
                  && domNode.getParentNode() != null) {
                String parentName = domNode.getParentNode().getNodeName();
                isCodeNode =
                    parentName.equals(JSP12Namespace.ElementName.SCRIPTLET)
                        || parentName.equals(JSP12Namespace.ElementName.EXPRESSION)
                        || parentName.equals(JSP12Namespace.ElementName.DECLARATION);
              }
            }
            if (isCodeNode) {
              if (regionStartOffset > startOffset) return regionStartOffset;
              else return startOffset;
            }
          }
        }
      }
    }
    return NO_VALID_CONTENT;
  }