/**
   * Creates a new inline method refactoring
   *
   * @param unit the compilation unit or class file
   * @param node the compilation unit node
   * @param selectionStart start
   * @param selectionLength length
   * @return returns the refactoring
   */
  public static InlineMethodRefactoring create(
      ITypeRoot unit, CompilationUnit node, int selectionStart, int selectionLength) {
    ASTNode target =
        RefactoringAvailabilityTester.getInlineableMethodNode(
            unit, node, selectionStart, selectionLength);
    if (target == null) return null;
    if (target.getNodeType() == ASTNode.METHOD_DECLARATION) {

      return new InlineMethodRefactoring(
          unit, (MethodDeclaration) target, selectionStart, selectionLength);
    } else {
      ICompilationUnit cu = (ICompilationUnit) unit;
      if (target.getNodeType() == ASTNode.METHOD_INVOCATION) {
        return new InlineMethodRefactoring(
            cu, (MethodInvocation) target, selectionStart, selectionLength);
      } else if (target.getNodeType() == ASTNode.SUPER_METHOD_INVOCATION) {
        return new InlineMethodRefactoring(
            cu, (SuperMethodInvocation) target, selectionStart, selectionLength);
      } else if (target.getNodeType() == ASTNode.CONSTRUCTOR_INVOCATION) {
        return new InlineMethodRefactoring(
            cu, (ConstructorInvocation) target, selectionStart, selectionLength);
      }
    }
    return null;
  }
 /*
  * Check if the node is in a block. We don't want to update declarations
  */
 private static boolean isNotInBlock(ASTNode parent) {
   ASTNode statement = parent.getParent();
   boolean isStatement = statement.getNodeType() != ASTNode.EXPRESSION_STATEMENT;
   ASTNode block = statement.getParent();
   boolean isBlock =
       block.getNodeType() == ASTNode.BLOCK || block.getNodeType() == ASTNode.SWITCH_STATEMENT;
   boolean isControlStatemenBody =
       ASTNodes.isControlStatementBody(statement.getLocationInParent());
   return isStatement || !(isBlock || isControlStatemenBody);
 }
Пример #3
0
  private ASTNode createTargetNode(
      ASTNode first, ASTNode last, boolean isMove, ASTNode replacingNode, TextEditGroup editGroup) {
    if (first == null || last == null) {
      throw new IllegalArgumentException();
    }

    NodeInfoStore nodeStore = this.rewriter.getNodeStore();
    ASTNode placeholder =
        nodeStore.newPlaceholderNode(first.getNodeType()); // revisit: could use list type
    if (placeholder == null) {
      throw new IllegalArgumentException(
          "Creating a target node is not supported for nodes of type"
              + first.getClass().getName()); // $NON-NLS-1$
    }

    Block internalPlaceHolder = nodeStore.createCollapsePlaceholder();
    CopySourceInfo info =
        getRewriteStore()
            .createRangeCopy(
                this.parent,
                this.childProperty,
                first,
                last,
                isMove,
                internalPlaceHolder,
                replacingNode,
                editGroup);
    nodeStore.markAsCopyTarget(placeholder, info);

    return placeholder;
  }
 /**
  * Collects the existing tags on the {@link IJavaElement} we have been activated on
  *
  * @param element
  * @param jcontext
  * @throws JavaModelException
  * @throws BadLocationException
  */
 private void collectExistingTags(
     IJavaElement element, JavaContentAssistInvocationContext jcontext) throws JavaModelException {
   if (element instanceof IMember) {
     IMember member = (IMember) element;
     ICompilationUnit cunit = jcontext.getCompilationUnit();
     if (cunit != null) {
       if (cunit.isWorkingCopy()) {
         cunit.reconcile(ICompilationUnit.NO_AST, false, false, null, null);
       }
       fParser.setSource(member.getSource().toCharArray());
       fParser.setKind(ASTParser.K_CLASS_BODY_DECLARATIONS);
       Map<String, String> options = element.getJavaProject().getOptions(true);
       options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
       fParser.setCompilerOptions(options);
       fParser.setStatementsRecovery(false);
       fParser.setResolveBindings(false);
       fParser.setBindingsRecovery(false);
       ASTNode ast = fParser.createAST(null);
       TagCollector collector = new TagCollector();
       if (ast.getNodeType() == ASTNode.TYPE_DECLARATION) {
         TypeDeclaration typeDeclaration = (TypeDeclaration) ast;
         List<BodyDeclaration> bodyDeclarations = typeDeclaration.bodyDeclarations();
         if (bodyDeclarations.size() == 1) {
           // only one element should be there as we are parsing a
           // specific member
           BodyDeclaration bodyDeclaration = bodyDeclarations.iterator().next();
           Javadoc javadoc = bodyDeclaration.getJavadoc();
           if (javadoc != null) {
             javadoc.accept(collector);
           }
         }
       }
     }
   }
 }
  @SuppressWarnings("rawtypes") // DOM AST API returns raw collections
  public SourcePosition getPosition() {
    final MirrorKind kind = _parent.kind();
    ASTNode astNode = null;
    switch (kind) {
      case ANNOTATION_MIRROR:
        final AnnotationMirrorImpl anno = (AnnotationMirrorImpl) _parent;
        astNode = anno.getASTNodeForElement(_name);
        break;
      case ANNOTATION_ELEMENT:
        final AnnotationElementDeclarationImpl element = (AnnotationElementDeclarationImpl) _parent;
        astNode = element.getAstNodeForDefault();
        break;
      default:
        throw new IllegalStateException(); // should never reach this point.
    }
    // did not come from source.
    if (astNode == null) return null;
    if (_index >= 0 && astNode.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
      final ArrayInitializer arrayInit = (ArrayInitializer) astNode;
      final List exprs = arrayInit.expressions();
      if (exprs != null && _index < exprs.size()) astNode = (ASTNode) exprs.get(_index);
    }
    if (astNode == null) return null;

    final CompilationUnit unit = getCompilationUnit();
    if (unit == null) return null;
    final int offset = astNode.getStartPosition();
    return new SourcePositionImpl(
        astNode.getStartPosition(),
        astNode.getLength(),
        unit.getLineNumber(offset),
        unit.getColumnNumber(offset),
        this);
  }
 /**
  * Converts an assignment, postfix expression or prefix expression into an assignable equivalent
  * expression using the getter.
  *
  * @param node the assignment/prefix/postfix node
  * @param astRewrite the astRewrite to use
  * @param getterExpression the expression to insert for read accesses or <code>null</code> if such
  *     an expression does not exist
  * @param variableType the type of the variable that the result will be assigned to
  * @param is50OrHigher <code>true</code> if a 5.0 or higher environment can be used
  * @return an expression that can be assigned to the type variableType with node being replaced by
  *     a equivalent expression using the getter
  */
 public static Expression getAssignedValue(
     ASTNode node,
     ASTRewrite astRewrite,
     Expression getterExpression,
     ITypeBinding variableType,
     boolean is50OrHigher) {
   InfixExpression.Operator op = null;
   AST ast = astRewrite.getAST();
   if (isNotInBlock(node)) return null;
   if (node.getNodeType() == ASTNode.ASSIGNMENT) {
     Assignment assignment = ((Assignment) node);
     Expression rightHandSide = assignment.getRightHandSide();
     Expression copiedRightOp = (Expression) astRewrite.createCopyTarget(rightHandSide);
     if (assignment.getOperator() == Operator.ASSIGN) {
       ITypeBinding rightHandSideType = rightHandSide.resolveTypeBinding();
       copiedRightOp =
           createNarrowCastIfNessecary(
               copiedRightOp, rightHandSideType, ast, variableType, is50OrHigher);
       return copiedRightOp;
     }
     if (getterExpression != null) {
       InfixExpression infix = ast.newInfixExpression();
       infix.setLeftOperand(getterExpression);
       infix.setOperator(ASTNodes.convertToInfixOperator(assignment.getOperator()));
       infix.setRightOperand(copiedRightOp);
       ITypeBinding infixType = infix.resolveTypeBinding();
       return createNarrowCastIfNessecary(infix, infixType, ast, variableType, is50OrHigher);
     }
   } else if (node.getNodeType() == ASTNode.POSTFIX_EXPRESSION) {
     PostfixExpression po = (PostfixExpression) node;
     if (po.getOperator() == PostfixExpression.Operator.INCREMENT)
       op = InfixExpression.Operator.PLUS;
     if (po.getOperator() == PostfixExpression.Operator.DECREMENT)
       op = InfixExpression.Operator.MINUS;
   } else if (node.getNodeType() == ASTNode.PREFIX_EXPRESSION) {
     PrefixExpression pe = (PrefixExpression) node;
     if (pe.getOperator() == PrefixExpression.Operator.INCREMENT)
       op = InfixExpression.Operator.PLUS;
     if (pe.getOperator() == PrefixExpression.Operator.DECREMENT)
       op = InfixExpression.Operator.MINUS;
   }
   if (op != null && getterExpression != null) {
     return createInfixInvocationFromPostPrefixExpression(
         op, getterExpression, ast, variableType, is50OrHigher);
   }
   return null;
 }
Пример #7
0
 /* (non-Javadoc)
  * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Javadoc)
  */
 public boolean visit(Javadoc node) {
   List tags = node.tags();
   ASTNode parent = node.getParent();
   if (parent != null) {
     switch (parent.getNodeType()) {
       case ASTNode.TYPE_DECLARATION:
         {
           TypeDeclaration type = (TypeDeclaration) parent;
           if (type.isInterface()) {
             processTags(
                 fType,
                 pruneTags(tags, type),
                 IApiJavadocTag.TYPE_INTERFACE,
                 IApiJavadocTag.MEMBER_NONE);
           } else {
             processTags(
                 fType,
                 pruneTags(tags, type),
                 IApiJavadocTag.TYPE_CLASS,
                 IApiJavadocTag.MEMBER_NONE);
           }
           break;
         }
       case ASTNode.METHOD_DECLARATION:
         {
           MethodDeclaration method = (MethodDeclaration) parent;
           String signature = Signatures.getMethodSignatureFromNode(method);
           if (signature != null) {
             String methodname = method.getName().getFullyQualifiedName();
             int member = IApiJavadocTag.MEMBER_METHOD;
             if (method.isConstructor()) {
               member = IApiJavadocTag.MEMBER_CONSTRUCTOR;
               methodname = "<init>"; // $NON-NLS-1$
             }
             IMethodDescriptor descriptor = fType.getMethod(methodname, signature);
             processTags(descriptor, pruneTags(tags, method), getEnclosingType(method), member);
           }
           break;
         }
       case ASTNode.FIELD_DECLARATION:
         {
           FieldDeclaration field = (FieldDeclaration) parent;
           List fields = field.fragments();
           VariableDeclarationFragment fragment = null;
           for (Iterator iter = fields.iterator(); iter.hasNext(); ) {
             fragment = (VariableDeclarationFragment) iter.next();
             processTags(
                 fType.getField(fragment.getName().getFullyQualifiedName()),
                 pruneTags(tags, field),
                 getEnclosingType(field),
                 IApiJavadocTag.MEMBER_FIELD);
           }
           break;
         }
     }
   }
   return false;
 }
  // https://bugs.eclipse.org/bugs/show_bug.cgi?id=388137
  public void testbug388137() throws Exception {
    this.workingCopies = new ICompilationUnit[1];
    IJavaProject project =
        createJavaProject("P1", new String[] {""}, new String[] {"CONVERTER_JCL15_LIB"}, "", "1.5");
    try {
      String contents =
          "package p;\n"
              + "import java.util.List;\n"
              + "public class X {\n"
              + "	public X(List list) {}\n"
              + "	public static class ListHandler implements Handler {\n"
              + "		List list = null;\n"
              + "		public ListHandler(List list) {\n"
              + " 	 		this.list = list;\n"
              + "		}\n"
              + "	}\n"
              + "}\n"
              + "interface Handler {}\n";
      addLibrary(project, "lib.jar", "src.zip", new String[] {"/P1/p/X.java", contents}, "1.5");

      this.workingCopies[0] = getWorkingCopy("/P1/q/Y.java", true);
      contents =
          "package q;\n"
              + "import p.X.ListHandler;\n"
              + "public class Y {\n"
              + "	public Object foo() {\n"
              + "		ListHandler sortHandler = new ListHandler(null);\n"
              + "		return sortHandler;"
              + "	}\n"
              + "}\n";
      ASTNode node = buildAST(contents, this.workingCopies[0], true);

      assertTrue("Should be a compilation unit", node instanceof CompilationUnit);
      CompilationUnit unit = (CompilationUnit) node;
      node = getASTNode(unit, 0, 0, 0);
      assertEquals(
          "Not an expression statement",
          ASTNode.VARIABLE_DECLARATION_STATEMENT,
          node.getNodeType());
      VariableDeclarationStatement statement = (VariableDeclarationStatement) node;
      List fragments = statement.fragments();
      assertEquals("Wrong size", 1, fragments.size());
      VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
      Expression expression = fragment.getInitializer();
      assertEquals(
          "Not a constructor invocation",
          ASTNode.CLASS_INSTANCE_CREATION,
          expression.getNodeType());
      ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) expression;
      IMethodBinding binding = classInstanceCreation.resolveConstructorBinding();
      JavaElement element = (JavaElement) binding.getJavaElement();
      assertNotNull("Null Element info", element.getElementInfo());
    } finally {
      deleteProject(project);
    }
  }
  //	 !!! -- +/- same as in ExtractTempRefactoring
  public boolean isLiteralNodeSelected() {
    ASTNode[] nodes = getSelectedNodes();
    if (nodes.length != 1) return false;
    ASTNode node = nodes[0];
    switch (node.getNodeType()) {
      case ASTNode.BOOLEAN_LITERAL:
      case ASTNode.CHARACTER_LITERAL:
      case ASTNode.NULL_LITERAL:
      case ASTNode.NUMBER_LITERAL:
        return true;

      default:
        return false;
    }
  }
Пример #10
0
 public boolean visit(AnonymousClassDeclaration node) {
   ASTNode name;
   ASTNode parent = node.getParent();
   switch (parent.getNodeType()) {
     case ASTNode.CLASS_INSTANCE_CREATION:
       name = ((ClassInstanceCreation) parent).getType();
       break;
     case ASTNode.ENUM_CONSTANT_DECLARATION:
       name = ((EnumConstantDeclaration) parent).getName();
       break;
     default:
       return true;
   }
   if (found(node, name) && this.resolveBinding) this.foundBinding = node.resolveBinding();
   return true;
 }
Пример #11
0
  public Collection<ConstructorDeclaration> getConstructors() {
    final List<ConstructorDeclaration> results = new ArrayList<ConstructorDeclaration>();
    if (isFromSource()) {
      // need to consult the ast since methods with broken signature
      // do not appear in bindings.
      final ITypeBinding typeBinding = getDeclarationBinding();
      final ASTNode node = _env.getASTNodeForBinding(typeBinding);
      if (node != null) {
        switch (node.getNodeType()) {
          case ASTNode.TYPE_DECLARATION:
          case ASTNode.ANNOTATION_TYPE_DECLARATION:
          case ASTNode.ENUM_DECLARATION:
            AbstractTypeDeclaration typeDecl = (AbstractTypeDeclaration) node;
            // built the ast based methods first.
            getASTConstructor(typeDecl, results);
            break;
          default:
            // the ast node for a type binding should be a AbstractTypeDeclaration.
            throw new IllegalStateException(
                "expecting a AbstractTypeDeclaration but got " //$NON-NLS-1$
                    + node.getClass().getName());
        }
      }
    }
    // build methods for binding type or
    // build the binding based method for source type.

    final IMethodBinding[] methods = getDeclarationBinding().getDeclaredMethods();
    for (IMethodBinding method : methods) {
      if (method.isSynthetic()) continue;
      if (method.isConstructor()) {
        Declaration mirrorDecl = Factory.createDeclaration(method, _env);
        if (mirrorDecl != null) results.add((ConstructorDeclaration) mirrorDecl);
      }
    }
    return results;
  }
  /*(non-Javadoc)
   * @see org.eclipse.jdt.internal.ui.text.correction.ASTRewriteCorrectionProposal#getRewrite()
   */
  @Override
  protected ASTRewrite getRewrite() {
    AST ast = fMethodDecl.getAST();

    ITypeBinding returnBinding = getReturnTypeBinding();

    if (fExistingReturn != null) {
      ASTRewrite rewrite = ASTRewrite.create(ast);

      Expression expression =
          evaluateReturnExpressions(ast, returnBinding, fExistingReturn.getStartPosition());
      if (expression != null) {
        rewrite.set(fExistingReturn, ReturnStatement.EXPRESSION_PROPERTY, expression, null);

        addLinkedPosition(rewrite.track(expression), true, RETURN_EXPRESSION_KEY);
      }
      return rewrite;
    } else {
      ASTRewrite rewrite = ASTRewrite.create(ast);

      Block block = fMethodDecl.getBody();

      List<Statement> statements = block.statements();
      int nStatements = statements.size();
      ASTNode lastStatement = null;
      if (nStatements > 0) {
        lastStatement = statements.get(nStatements - 1);
      }

      if (returnBinding != null
          && lastStatement instanceof ExpressionStatement
          && lastStatement.getNodeType() != ASTNode.ASSIGNMENT) {
        Expression expression = ((ExpressionStatement) lastStatement).getExpression();
        ITypeBinding binding = expression.resolveTypeBinding();
        if (binding != null && binding.isAssignmentCompatible(returnBinding)) {
          Expression placeHolder = (Expression) rewrite.createMoveTarget(expression);

          ReturnStatement returnStatement = ast.newReturnStatement();
          returnStatement.setExpression(placeHolder);

          rewrite.replace(lastStatement, returnStatement, null);
          return rewrite;
        }
      }

      int offset;
      if (lastStatement == null) {
        offset = block.getStartPosition() + 1;
      } else {
        offset = lastStatement.getStartPosition() + lastStatement.getLength();
      }
      ReturnStatement returnStatement = ast.newReturnStatement();
      Expression expression = evaluateReturnExpressions(ast, returnBinding, offset);

      returnStatement.setExpression(expression);

      rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertLast(returnStatement, null);

      addLinkedPosition(
          rewrite.track(returnStatement.getExpression()), true, RETURN_EXPRESSION_KEY);
      return rewrite;
    }
  }
Пример #13
0
 /**
  * Method to post process returned flags from the {@link Javadoc} node of the element
  *
  * @param tags the tags to process
  * @param element the {@link ASTNode} the tag appears on
  * @return the list of valid tags to process restrictions for
  */
 private List pruneTags(final List tags, ASTNode node) {
   ArrayList pruned = new ArrayList(tags.size());
   TagElement tag = null;
   switch (node.getNodeType()) {
     case ASTNode.TYPE_DECLARATION:
       {
         TypeDeclaration type = (TypeDeclaration) node;
         int flags = type.getModifiers();
         for (Iterator iterator = tags.iterator(); iterator.hasNext(); ) {
           tag = (TagElement) iterator.next();
           String tagname = tag.getTagName();
           if (type.isInterface()
               && ("@noextend".equals(tagname)
                   || //$NON-NLS-1$
                   "@noimplement".equals(tagname))) { // $NON-NLS-1$
             pruned.add(tag);
           } else {
             if ("@noextend".equals(tagname)) { // $NON-NLS-1$
               if (!Flags.isFinal(flags)) {
                 pruned.add(tag);
                 continue;
               }
             }
             if ("@noinstantiate".equals(tagname)) { // $NON-NLS-1$
               if (!Flags.isAbstract(flags)) {
                 pruned.add(tag);
                 continue;
               }
             }
           }
         }
         break;
       }
     case ASTNode.METHOD_DECLARATION:
       {
         MethodDeclaration method = (MethodDeclaration) node;
         int flags = method.getModifiers();
         for (Iterator iterator = tags.iterator(); iterator.hasNext(); ) {
           tag = (TagElement) iterator.next();
           if ("@noreference".equals(tag.getTagName())) { // $NON-NLS-1$
             pruned.add(tag);
             continue;
           }
           if ("@nooverride".equals(tag.getTagName())) { // $NON-NLS-1$
             ASTNode parent = method.getParent();
             int pflags = 0;
             if (parent instanceof BodyDeclaration) {
               pflags = ((BodyDeclaration) parent).getModifiers();
             }
             if (!Flags.isFinal(flags) && !Flags.isStatic(flags) && !Flags.isFinal(pflags)) {
               pruned.add(tag);
               continue;
             }
           }
         }
         break;
       }
     case ASTNode.FIELD_DECLARATION:
       {
         FieldDeclaration field = (FieldDeclaration) node;
         for (Iterator iterator = tags.iterator(); iterator.hasNext(); ) {
           tag = (TagElement) iterator.next();
           boolean isfinal = Flags.isFinal(field.getModifiers());
           if (isfinal || (isfinal && Flags.isStatic(field.getModifiers()))) {
             break;
           }
           if ("@noreference".equals(tag.getTagName())) { // $NON-NLS-1$
             pruned.add(tag);
             break;
           }
         }
         break;
       }
   }
   return pruned;
 }
Пример #14
0
  private boolean isClosed(IDocument document, int offset, int length) {

    CompilationUnitInfo info = getCompilationUnitForMethod(document, offset);
    if (info == null) return false;

    CompilationUnit compilationUnit = null;
    try {
      ASTParser parser = ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
      parser.setSource(info.buffer);
      compilationUnit = (CompilationUnit) parser.createAST(null);
    } catch (ArrayIndexOutOfBoundsException x) {
      // work around for parser problem
      return false;
    }

    IProblem[] problems = compilationUnit.getProblems();
    for (int i = 0; i != problems.length; ++i) {
      if (problems[i].getID() == IProblem.UnmatchedBracket) return true;
    }

    final int relativeOffset = offset - info.delta;

    ASTNode node = NodeFinder.perform(compilationUnit, relativeOffset, length);

    if (length == 0) {
      while (node != null
          && (relativeOffset == node.getStartPosition()
              || relativeOffset == node.getStartPosition() + node.getLength()))
        node = node.getParent();
    }

    if (node == null) return false;

    switch (node.getNodeType()) {
      case ASTNode.BLOCK:
        return getBlockBalance(document, offset, fPartitioning) <= 0;

      case ASTNode.IF_STATEMENT:
        {
          IfStatement ifStatement = (IfStatement) node;
          Expression expression = ifStatement.getExpression();
          IRegion expressionRegion = createRegion(expression, info.delta);
          Statement thenStatement = ifStatement.getThenStatement();
          IRegion thenRegion = createRegion(thenStatement, info.delta);

          // between expression and then statement
          if (expressionRegion.getOffset() + expressionRegion.getLength() <= offset
              && offset + length <= thenRegion.getOffset()) return thenStatement != null;

          Statement elseStatement = ifStatement.getElseStatement();
          IRegion elseRegion = createRegion(elseStatement, info.delta);

          if (elseStatement != null) {
            int sourceOffset = thenRegion.getOffset() + thenRegion.getLength();
            int sourceLength = elseRegion.getOffset() - sourceOffset;
            IRegion elseToken =
                getToken(
                    document,
                    new Region(sourceOffset, sourceLength),
                    ITerminalSymbols.TokenNameelse);
            return elseToken != null
                && elseToken.getOffset() + elseToken.getLength() <= offset
                && offset + length < elseRegion.getOffset();
          }
        }
        break;

      case ASTNode.WHILE_STATEMENT:
      case ASTNode.FOR_STATEMENT:
        {
          Expression expression =
              node.getNodeType() == ASTNode.WHILE_STATEMENT
                  ? ((WhileStatement) node).getExpression()
                  : ((ForStatement) node).getExpression();
          IRegion expressionRegion = createRegion(expression, info.delta);
          Statement body =
              node.getNodeType() == ASTNode.WHILE_STATEMENT
                  ? ((WhileStatement) node).getBody()
                  : ((ForStatement) node).getBody();
          IRegion bodyRegion = createRegion(body, info.delta);

          // between expression and body statement
          if (expressionRegion.getOffset() + expressionRegion.getLength() <= offset
              && offset + length <= bodyRegion.getOffset()) return body != null;
        }
        break;

      case ASTNode.DO_STATEMENT:
        {
          DoStatement doStatement = (DoStatement) node;
          IRegion doRegion = createRegion(doStatement, info.delta);
          Statement body = doStatement.getBody();
          IRegion bodyRegion = createRegion(body, info.delta);

          if (doRegion.getOffset() + doRegion.getLength() <= offset
              && offset + length <= bodyRegion.getOffset()) return body != null;
        }
        break;
    }

    return true;
  }