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(); } }