private void writeConstantValue(Value v) throws IOException {
    Node node = tool.getDeclarationNode(v);
    PhasedUnit pu = tool.getDeclarationUnit(v);
    if (pu == null || !(node instanceof Tree.AttributeDeclaration)) {
      return;
    }

    Tree.AttributeDeclaration attribute = (Tree.AttributeDeclaration) node;
    Tree.SpecifierOrInitializerExpression specifierExpression =
        attribute.getSpecifierOrInitializerExpression();
    if (specifierExpression == null || specifierExpression.getExpression() == null) {
      return;
    }

    Token startToken = specifierExpression.getExpression().getToken();
    int startLine = startToken.getLine();
    int startLinePosition = startToken.getCharPositionInLine();

    Token endToken = attribute.getEndToken();
    int endLine = endToken.getLine();
    int endLinePosition = endToken.getCharPositionInLine();

    StringBuilder valueBuilder = new StringBuilder(" ");
    BufferedReader sourceCodeReader =
        new BufferedReader(new InputStreamReader(pu.getUnitFile().getInputStream()));
    try {
      int lineIndex = 1;
      String line = sourceCodeReader.readLine();
      while (line != null) {
        if (lineIndex == startLine && lineIndex == endLine) {
          valueBuilder.append(line.substring(startLinePosition, endLinePosition));
          break;
        } else if (lineIndex == startLine) {
          valueBuilder.append(line.substring(startLinePosition, line.length()));
        } else if (lineIndex > startLine && lineIndex < endLine) {
          valueBuilder.append("\n");
          valueBuilder.append(line);
        } else if (lineIndex == endLine) {
          valueBuilder.append("\n");
          valueBuilder.append(line.substring(0, endLinePosition));
          break;
        }

        line = sourceCodeReader.readLine();
        lineIndex++;
      }
    } finally {
      sourceCodeReader.close();
    }

    String value = valueBuilder.toString();
    int newLineIndex = value.indexOf("\n");
    String valueFirstLine = newLineIndex != -1 ? value.substring(0, newLineIndex) : value;

    around("span class='specifier-operator'", " = ");
    around("span class='specifier-start'", valueFirstLine);
    if (newLineIndex != -1) {
      around(
          "a class='specifier-ellipsis' href='#' title='Click for expand the rest of value.'",
          "...");
      open("div class='specifier-rest'");
      write(value.substring(newLineIndex + 1));
      around("span class='specifier-semicolon'", ";");
      close("div");
    } else {
      around("span class='specifier-semicolon'", ";");
    }
  }
  public static String getInitialValueDescription(
      final Declaration dec, CeylonParseController cpc) {
    if (cpc != null) {
      Node refnode = getReferencedNode(dec);
      Tree.SpecifierOrInitializerExpression sie = null;
      String arrow = null;
      if (refnode instanceof Tree.AttributeDeclaration) {
        Tree.AttributeDeclaration ad = (Tree.AttributeDeclaration) refnode;
        sie = ad.getSpecifierOrInitializerExpression();
        arrow = " = ";
      } else if (refnode instanceof Tree.MethodDeclaration) {
        Tree.MethodDeclaration md = (Tree.MethodDeclaration) refnode;
        sie = md.getSpecifierExpression();
        arrow = " => ";
      }
      Tree.CompilationUnit lcu = cpc.getLastCompilationUnit();
      if (sie == null) {
        class FindInitializerVisitor extends Visitor {
          Tree.SpecifierOrInitializerExpression result;

          @Override
          public void visit(Tree.InitializerParameter that) {
            super.visit(that);
            Declaration d = that.getParameterModel().getModel();
            if (d != null && d.equals(dec)) {
              result = that.getSpecifierExpression();
            }
          }
        }
        FindInitializerVisitor fiv = new FindInitializerVisitor();
        fiv.visit(lcu);
        sie = fiv.result;
      }
      if (sie != null) {
        Tree.Expression e = sie.getExpression();
        if (e != null) {
          Tree.Term term = e.getTerm();
          if (term instanceof Tree.Literal) {
            String text = term.getToken().getText();
            if (text.length() < 20) {
              return arrow + text;
            }
          } else if (term instanceof Tree.BaseMemberOrTypeExpression) {
            Tree.BaseMemberOrTypeExpression bme = (Tree.BaseMemberOrTypeExpression) term;
            Tree.Identifier id = bme.getIdentifier();
            if (id != null && bme.getTypeArguments() == null) {
              return arrow + id.getText();
            }
          } else if (term != null) {
            Unit unit = lcu.getUnit();
            if (term.getUnit().equals(unit)) {
              String impl = Nodes.text(term, cpc.getTokens());
              if (impl.length() < 10) {
                return arrow + impl;
              }
            }
          }
          // don't have the token stream :-/
          // TODO: figure out where to get it from!
          return arrow + "...";
        }
      }
    }
    return "";
  }
  public void defaultedParameter(Tree.SpecifierOrInitializerExpression d) {
    if (annotationConstructor != null) {
      AnnotationConstructorParameter annotationConstructorParameter =
          instantiation
              .getConstructorParameters()
              .get(instantiation.getConstructorParameters().size() - 1);

      Declaration t = d.getUnit().getTrueValueDeclaration();
      Declaration f = d.getUnit().getFalseValueDeclaration();
      Term term = d.getExpression().getTerm();
      if (term instanceof Tree.InvocationExpression) {
        Tree.Primary primary = ((Tree.InvocationExpression) term).getPrimary();
        if (primary instanceof Tree.BaseMemberOrTypeExpression
            && (isAnnotationConstructor(
                    ((Tree.BaseMemberOrTypeExpression) primary).getDeclaration())
                || isAnnotationClass(
                    ((Tree.BaseMemberOrTypeExpression) primary).getDeclaration()))) {
          final AnnotationInvocation prevInstantiation = this.instantiation;
          this.instantiation = new AnnotationInvocation();
          if (isAnnotationConstructor(
              ((Tree.BaseMemberOrTypeExpression) primary).getDeclaration())) {
            Method constructor =
                (Method) ((Tree.BaseMemberOrTypeExpression) primary).getDeclaration();
            instantiation.setConstructorDeclaration(constructor);
            instantiation
                .getConstructorParameters()
                .addAll(
                    ((AnnotationInvocation) constructor.getAnnotationConstructor())
                        .getConstructorParameters());
          }
          checkingDefaults = true;

          super.visit(d);

          annotationConstructorParameter.setDefaultArgument(this.term);
          this.term = null;
          checkingDefaults = false;
          this.instantiation = prevInstantiation;
        } else {
          errorDefaultedParameter(d);
        }
      } else if (term instanceof Tree.Literal
          || (term instanceof Tree.BaseMemberExpression
              && (((Tree.BaseMemberExpression) term).getDeclaration().equals(t)
                  || ((Tree.BaseMemberExpression) term).getDeclaration().equals(f)
                  || ((Tree.BaseMemberExpression) term).getDeclaration().isParameter()
                  || Decl.isAnonCaseOfEnumeratedType((Tree.BaseMemberExpression) term)))) {
        checkingDefaults = true;

        super.visit(d);

        annotationConstructorParameter.setDefaultArgument(this.term);
        this.term = null;
        checkingDefaults = false;
      } else if (term instanceof Tree.Tuple || term instanceof Tree.SequenceEnumeration) {
        // TODO Tuples and SequenceEnumerations of the above cases should also be allowed
        checkingDefaults = true;

        super.visit(d);

        annotationConstructorParameter.setDefaultArgument(this.term);
        this.term = null;
        checkingDefaults = false;
      } else {
        errorDefaultedParameter(d);
      }
    }
  }