private void checkVariable(Tree.Term term, Node node) {
   if (isEffectivelyBaseMemberExpression(term)) { // Note: other cases handled in ExpressionVisitor
     Tree.StaticMemberOrTypeExpression mte = (Tree.StaticMemberOrTypeExpression) term;
     Declaration member = mte.getDeclaration();
     if (member == declaration) {
       if ((declaration.isFormal() || declaration.isDefault()) && !isForwardReferenceable()) {
         term.addError(
             "member is formal or default and may not be assigned here: '"
                 + member.getName()
                 + "'");
       } else if (!isVariable() && !isLate()) {
         if (member instanceof Value) {
           if (node instanceof Tree.AssignOp) {
             term.addError(
                 "value is not a variable and may not be assigned here: '"
                     + member.getName()
                     + "'",
                 803);
           } else {
             term.addError("value is not a variable: '" + member.getName() + "'", 800);
           }
         } else {
           term.addError("not a variable value: '" + member.getName() + "'");
         }
       }
     }
   }
 }
 @Override
 public void visit(Tree.AttributeDeclaration that) {
   if (that.getDeclarationModel() == declaration) {
     Tree.SpecifierOrInitializerExpression sie = that.getSpecifierOrInitializerExpression();
     if (sie != null) {
       super.visit(that);
       specify();
     } else {
       super.visit(that);
       if (declaration.isToplevel() && !isNativeHeader(declaration) && !isLate()) {
         if (isVariable()) {
           that.addError(
               "toplevel variable value must be initialized: '" + declaration.getName() + "'");
         } else {
           that.addError("toplevel value must be specified: '" + declaration.getName() + "'");
         }
       } else if (declaration.isClassOrInterfaceMember()
           && !isNativeHeader(declaration)
           && !declaration.isFormal()
           && that.getDeclarationModel().getInitializerParameter() == null
           && !that.getDeclarationModel().isLate()
           && declarationSection) {
         that.addError(
             "forward declaration may not occur in declaration section: '"
                 + declaration.getName()
                 + "'",
             1450);
       }
     }
   } else {
     super.visit(that);
   }
 }
 private boolean isSharedDeclarationUninitialized() {
   return (declaration.isShared() || declaration.getOtherInstanceAccess())
       && !declaration.isFormal()
       && !isNativeHeader(declaration)
       && !isLate()
       && !specified.definitely;
 }
 @Override
 public void visit(Tree.MethodDeclaration that) {
   if (that.getDeclarationModel() == declaration) {
     if (that.getSpecifierExpression() != null) {
       specify();
       super.visit(that);
     } else {
       super.visit(that);
       if (declaration.isToplevel() && !isNativeHeader(declaration)) {
         that.addError(
             "toplevel function must be specified: '"
                 + declaration.getName()
                 + "' may not be forward declared");
       } else if (declaration.isClassMember()
           && !isNativeHeader(declaration)
           && isInNativeContainer(declaration)) {
         that.addError(
             "member in native container must be native: '" + declaration.getName() + "'", 1450);
       } else if (declaration.isClassMember()
           && !isNativeHeader(declaration)
           && !declaration.isFormal()
           && that.getDeclarationModel().getInitializerParameter() == null
           && declarationSection) {
         that.addError(
             "forward declaration may not occur in declaration section: '"
                 + declaration.getName()
                 + "'",
             1450);
       } else if (declaration.isInterfaceMember()
           && !isNativeHeader(declaration)
           && !declaration.isFormal()) {
         that.addError(
             "interface method must be formal or specified: '" + declaration.getName() + "'",
             1400);
       }
     }
   } else {
     super.visit(that);
   }
 }
 @Override
 public void visit(Tree.SpecifierStatement that) {
   Tree.Term term = that.getBaseMemberExpression();
   boolean parameterized = false;
   while (term instanceof Tree.ParameterizedExpression) {
     Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) term;
     term = pe.getPrimary();
     parameterized = true;
   }
   if (term instanceof Tree.StaticMemberOrTypeExpression) {
     Tree.StaticMemberOrTypeExpression bme = (Tree.StaticMemberOrTypeExpression) term;
     //            Declaration member = getTypedDeclaration(bme.getScope(),
     //                    name(bme.getIdentifier()), null, false, bme.getUnit());
     Declaration member = bme.getDeclaration();
     if (member == declaration) {
       if ((declaration.isFormal() || declaration.isDefault()) && !isForwardReferenceable()) {
         // TODO: is this error correct?! look at the condition above
         bme.addError(
             "member is formal and may not be specified: '"
                 + member.getName()
                 + "' is declared formal");
       }
       if (that.getRefinement()) {
         declare();
       }
       Tree.SpecifierExpression se = that.getSpecifierExpression();
       boolean lazy = se instanceof Tree.LazySpecifierExpression;
       if (declaration instanceof Value) {
         Value value = (Value) declaration;
         if (!value.isVariable() && lazy != value.isTransient()) {
           // check that all assignments to a non-variable, in
           // different paths of execution, all use the same
           // kind of specifier, all =>, or all =
           // TODO: sometimes this error appears only because
           //       of a later line which illegally reassigns
           se.addError(
               "value must be specified using => lazy specifier: '" + member.getName() + "'");
         }
         if (lazy) {
           if (value.isVariable()) {
             se.addError(
                 "variable value may not be specified using => lazy specifier: '"
                     + member.getName()
                     + "'");
           } else if (value.isLate()) {
             se.addError(
                 "late reference may not be specified using => lazy specifier: '"
                     + member.getName()
                     + "'");
           }
         }
       }
       if (!lazy || !parameterized) {
         se.visit(this);
       }
       boolean constant = !isVariable() && !isLate();
       Scope scope = that.getScope();
       if (constant && !declaration.isDefinedInScope(scope)) {
         // this error is added by ExpressionVisitor
         //                    that.addError("inherited member is not variable and may not be
         // specified here: '" +
         //                            member.getName() + "'");
       } else if (!declared && constant) {
         bme.addError(shortdesc() + " is not yet declared: '" + member.getName() + "'");
       } else if (inLoop && constant && !(endsInBreakReturnThrow && lastContinue == null)) {
         if (specified.definitely) {
           bme.addError(
               longdesc() + " is aready definitely specified: '" + member.getName() + "'", 803);
         } else {
           bme.addError(
               longdesc() + " is not definitely unspecified in loop: '" + member.getName() + "'",
               803);
         }
       } else if (withinDeclaration && constant && !that.getRefinement()) {
         Declaration dec = getContainingDeclarationOfScope(scope);
         if (dec != null && dec.equals(member)) {
           bme.addError(
               "cannot specify "
                   + shortdesc()
                   + " from within its own body: '"
                   + member.getName()
                   + "'");
         } else {
           bme.addError(
               "cannot specify "
                   + shortdesc()
                   + " declared in outer scope: '"
                   + member.getName()
                   + "'",
               803);
         }
       } else if (specified.possibly && constant) {
         if (specified.definitely) {
           bme.addError(
               longdesc() + " is aready definitely specified: '" + member.getName() + "'", 803);
         } else {
           bme.addError(
               longdesc() + " is not definitely unspecified: '" + member.getName() + "'", 803);
         }
       } else {
         specify();
         term.visit(this);
       }
       if (lazy && parameterized) {
         se.visit(this);
       }
     } else {
       super.visit(that);
     }
   } else {
     super.visit(that);
   }
 }
  private void visitReference(Tree.Primary that) {
    Declaration member;
    boolean assigned;
    boolean metamodel;
    if (that instanceof Tree.MemberOrTypeExpression) {
      Tree.MemberOrTypeExpression mte = (Tree.MemberOrTypeExpression) that;
      member = mte.getDeclaration();
      assigned = mte.getAssigned();
      metamodel = false;
    } else if (that instanceof Tree.MetaLiteral) {
      Tree.MetaLiteral ml = (Tree.MetaLiteral) that;
      member = ml.getDeclaration();
      assigned = false;
      metamodel = true;
    } else {
      return;
    }

    if (member == declaration && member.isDefinedInScope(that.getScope())) {
      if (!declared) {
        // you are allowed to refer to later
        // declarations in a class declaration
        // section or interface
        if (withinAttributeInitializer
            && member instanceof Value
            && !(((Value) member).isTransient())) {
          that.addError(
              "reference to value within its initializer: '" + member.getName() + "'", 1460);
        } else if (!metamodel && !isForwardReferenceable() && !hasParameter) {
          Scope container = declaration.getContainer();
          if (container instanceof Class) {
            that.addError(
                "forward reference to class member in initializer: '"
                    + member.getName()
                    + "' is not yet declared (forward references must occur in declaration section)");
          } else {
            that.addError(
                "forward reference to local declaration: '"
                    + member.getName()
                    + "' is not yet declared");
          }
        }
      } else if (!specified.definitely || declaration.isFormal()) {
        // you are allowed to refer to formal
        // declarations in a class declaration
        // section or interface
        if (declaration.isFormal()) {
          if (!isForwardReferenceable()) {
            that.addError(
                "formal member may not be used in initializer: '" + member.getName() + "'");
          }
        } else if (!metamodel
            && !isNativeHeader(declaration)
            && (!isLate() || !isForwardReferenceable())) {
          if (isVariable()) {
            that.addError("not definitely initialized: '" + member.getName() + "'");
          } else {
            that.addError("not definitely specified: '" + member.getName() + "'");
          }
        }
      }
      if (!assigned && member.isDefault() && !isForwardReferenceable()) {
        that.addError("default member may not be used in initializer: '" + member.getName() + "'");
      }
      if (inAnonFunctionOrComprehension && specified.definitely && isVariable()) {
        that.addError(
            "variable member may not be captured by comprehension or function in extends clause: '"
                + member.getName()
                + "'");
      }
    }
  }
  @Deprecated
  // replaced by RefineFormalMembersQuickFix.ceylon
  private void refineFormalMembers(IDocument document) throws ExecutionException {
    if (rootNode == null) return;
    TextChange change = new DocumentChange("Refine Members", document);
    change.setEdit(new MultiTextEdit());
    // TODO: copy/pasted from CeylonQuickFixAssistant
    Tree.Body body;
    int offset;
    if (node instanceof Tree.ClassDefinition) {
      ClassDefinition classDefinition = (Tree.ClassDefinition) node;
      body = classDefinition.getClassBody();
      offset = -1;
    } else if (node instanceof Tree.InterfaceDefinition) {
      Tree.InterfaceDefinition interfaceDefinition = (Tree.InterfaceDefinition) node;
      body = interfaceDefinition.getInterfaceBody();
      offset = -1;
    } else if (node instanceof Tree.ObjectDefinition) {
      Tree.ObjectDefinition objectDefinition = (Tree.ObjectDefinition) node;
      body = objectDefinition.getClassBody();
      offset = -1;
    } else if (node instanceof Tree.ObjectExpression) {
      Tree.ObjectExpression objectExpression = (Tree.ObjectExpression) node;
      body = objectExpression.getClassBody();
      offset = -1;
    } else if (node instanceof Tree.ClassBody || node instanceof Tree.InterfaceBody) {
      body = (Tree.Body) node;
      IEditorPart editor = getCurrentEditor();
      if (editor instanceof CeylonEditor) {
        CeylonEditor ce = (CeylonEditor) editor;
        offset = ce.getSelection().getOffset();
      } else {
        offset = -1;
      }
    } else {
      return;
    }
    if (body == null) {
      return;
    }
    boolean isInterface = body instanceof Tree.InterfaceBody;
    List<Tree.Statement> statements = body.getStatements();
    String indent;
    //        String bodyIndent = getIndent(body, document);
    String bodyIndent = utilJ2C().indents().getIndent(node, document);
    String delim = utilJ2C().indents().getDefaultLineDelimiter(document);
    if (statements.isEmpty()) {
      indent = delim + bodyIndent + utilJ2C().indents().getDefaultIndent();
      if (offset < 0) {
        offset = body.getStartIndex() + 1;
      }
    } else {
      Tree.Statement statement = statements.get(statements.size() - 1);
      indent = delim + utilJ2C().indents().getIndent(statement, document);
      if (offset < 0) {
        offset = statement.getEndIndex();
      }
    }
    StringBuilder result = new StringBuilder();
    Set<Declaration> already = new HashSet<Declaration>();
    ClassOrInterface ci = (ClassOrInterface) node.getScope();
    Unit unit = node.getUnit();
    Set<String> ambiguousNames = new HashSet<String>();
    // TODO: does not return unrefined overloaded
    //      versions of a method with one overlaad
    //      already refined
    Collection<DeclarationWithProximity> proposals =
        ci.getMatchingMemberDeclarations(unit, ci, "", 0).values();
    for (DeclarationWithProximity dwp : proposals) {
      Declaration dec = dwp.getDeclaration();
      for (Declaration d : overloads(dec)) {
        try {
          if (d.isFormal() && ci.isInheritedFromSupertype(d)) {
            appendRefinementText(isInterface, indent, result, ci, unit, d);
            importProposals().importSignatureTypes(d, rootNode, already);
            ambiguousNames.add(d.getName());
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    for (TypeDeclaration superType : ci.getSupertypeDeclarations()) {
      for (Declaration m : superType.getMembers()) {
        try {
          if (m.getName() != null && m.isShared()) {
            Declaration r = ci.getMember(m.getName(), null, false);
            if ((r == null || !r.refines(m) && !r.getContainer().equals(ci))
                && ambiguousNames.add(m.getName())) {
              appendRefinementText(isInterface, indent, result, ci, unit, m);
              importProposals().importSignatureTypes(m, rootNode, already);
            }
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

    try {
      if (document.getChar(offset) == '}' && result.length() > 0) {
        result.append(delim).append(bodyIndent);
      }
    } catch (BadLocationException e) {
      e.printStackTrace();
    }
    importProposals().applyImports(change, already, rootNode, document);
    change.addEdit(new InsertEdit(offset, result.toString()));
    change.initializeValidationData(null);
    try {
      getWorkspace().run(new PerformChangeOperation(change), new NullProgressMonitor());
    } catch (CoreException ce) {
      ce.printStackTrace();
    }
  }