private CeylonParseController parse() {
   CeylonParseController cpc = new CeylonParseController();
   cpc.initialize(
       editor.getParseController().getPath(), editor.getParseController().getProject(), null);
   cpc.parse(editor.getCeylonSourceViewer().getDocument(), new NullProgressMonitor(), null);
   return cpc;
 }
 static int nextTokenType(CeylonParseController cpc, CommonToken token) {
   for (int i = token.getTokenIndex() + 1; i < cpc.getTokens().size(); i++) {
     CommonToken tok = cpc.getTokens().get(i);
     if (tok.getChannel() != CommonToken.HIDDEN_CHANNEL) {
       return tok.getType();
     }
   }
   return -1;
 }
 static void addPackageDescriptorCompletion(
     CeylonParseController cpc, int offset, String prefix, List<ICompletionProposal> result) {
   if (!"package".startsWith(prefix)) return;
   IFile file = cpc.getProject().getFile(cpc.getPath());
   String packageName = getPackageName(file);
   if (packageName != null) {
     result.add(new PackageDescriptorProposal(offset, prefix, packageName));
   }
 }
  private boolean terminateWithSemicolon() throws Exception {
    final IDocument doc = editor.getCeylonSourceViewer().getDocument();
    final TextChange change = new DocumentChange("Terminate Statement", doc);
    change.setEdit(new MultiTextEdit());
    CeylonParseController parser = parse();
    CompilationUnit rootNode = parser.getRootNode();
    IRegion li = getLineInfo(doc);
    String lineText = doc.get(li.getOffset(), li.getLength());
    final List<CommonToken> tokens = parser.getTokens();
    // final int startOfCodeInLine = getCodeStart(li, lineText, tokens);
    final int endOfCodeInLine = getCodeEnd(li, lineText, tokens);
    if (!doc.get(endOfCodeInLine, 1).equals(";")) {
      new Processor() {
        @Override
        public void visit(Tree.Annotation that) {
          super.visit(that);
          terminateWithSemicolon(that);
        }

        @Override
        public void visit(Tree.StatementOrArgument that) {
          super.visit(that);
          if (that instanceof Tree.ExecutableStatement && !(that instanceof Tree.ControlStatement)
              || that instanceof Tree.AttributeDeclaration
              || that instanceof Tree.MethodDeclaration
              || that instanceof Tree.ClassDeclaration
              || that instanceof Tree.InterfaceDeclaration
              || that instanceof Tree.SpecifiedArgument) {
            terminateWithSemicolon(that);
          }
        }

        private void terminateWithSemicolon(Node that) {
          try {
            if (that.getStartIndex() <= endOfCodeInLine && that.getStopIndex() >= endOfCodeInLine) {
              Token et = that.getEndToken();
              if (et == null
                  || et.getType() != CeylonLexer.SEMICOLON
                  || that.getStopIndex() > endOfCodeInLine) {
                if (!change.getEdit().hasChildren()) {
                  change.addEdit(new InsertEdit(endOfCodeInLine + 1, ";"));
                }
              }
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }.visit(rootNode);
      if (change.getEdit().hasChildren()) {
        change.perform(new NullProgressMonitor());
        return true;
      }
    }
    return false;
  }
 static void addCurrentPackageNameCompletion(
     CeylonParseController cpc, int offset, String prefix, List<ICompletionProposal> result) {
   IFile file = cpc.getProject().getFile(cpc.getPath());
   String moduleName = getPackageName(file);
   if (moduleName != null) {
     result.add(
         new CompletionProposal(
             offset, prefix, isModuleDescriptor(cpc) ? MODULE : PACKAGE, moduleName, moduleName));
   }
 }
  @Override
  protected IStructureComparator createStructureComparator(
      Object input,
      IDocument document,
      ISharedDocumentAdapter sharedDocumentAdapter,
      IProgressMonitor monitor)
      throws CoreException {

    if (input instanceof CeylonDocumentRangeNode) {
      return (CeylonDocumentRangeNode) input;
    }

    final boolean isEditable;
    if (input instanceof IEditableContent) {
      IEditableContent ec = (IEditableContent) input;
      isEditable = ec.isEditable();
    } else {
      isEditable = false;
    }

    StructureRootNode structureRootNode =
        new StructureRootNode(document, input, this, sharedDocumentAdapter) {
          @Override
          public boolean isEditable() {
            return isEditable;
          }
        };

    CeylonParseController pc = new CeylonParseController();
    if (input instanceof ResourceNode) {
      ResourceNode node = (ResourceNode) input;
      IResource file = node.getResource();
      pc.initialize(file.getProjectRelativePath(), file.getProject(), null);
    } else {
      pc.initialize(null, null, null);
    }

    if (pc.parseAndTypecheck(document, 10, monitor, null) != null) {
      // now visit the model, creating TreeCompareNodes for each ModelTreeNode
      CeylonOutlineNode tree =
          new CeylonOutlineBuilder() {
            // don't create nodes for shortcut refinement
            // because we can't distinguish them w/o a
            // full typecheck
            public void visit(Tree.SpecifierStatement that) {}
          }.buildTree(pc);
      if (tree != null) {
        buildCompareTree(tree, structureRootNode, document);
      }
    }

    return structureRootNode;
  }
 @Override
 public boolean isEnabled() {
   IEditorPart editor = getCurrentEditor();
   if (super.isEnabled()
       && editor instanceof CeylonEditor
       && editor.getEditorInput() instanceof IFileEditorInput) {
     CeylonParseController cpc = ((CeylonEditor) editor).getParseController();
     return cpc == null || cpc.getRootNode() == null ? false : true;
     // !cpc.getRootNode().getImportList().getImports().isEmpty();
   }
   return false;
 }
 @Override
 public IHyperlink[] detectHyperlinks(
     ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
   if (controller == null || controller.getLastCompilationUnit() == null) {
     return null;
   } else {
     Node node =
         findNode(
             controller.getLastCompilationUnit(),
             controller.getTokens(),
             region.getOffset(),
             region.getOffset() + region.getLength());
     if (node == null) {
       return null;
     } else {
       Node id = getIdentifyingNode(node);
       if (id == null) {
         return null;
       } else {
         Referenceable referenceable = getReferencedModel(node);
         Backends supportedBackends = supportedBackends();
         if (referenceable instanceof Declaration) {
           Declaration dec = (Declaration) referenceable;
           if (dec.isNative()) {
             if (supportedBackends.none()) {
               return null;
             } else {
               referenceable = resolveNative(referenceable, dec, supportedBackends);
             }
           } else {
             if (!supportedBackends.none()) {
               return null;
             }
           }
         } else { // Module or package descriptors
           if (!supportedBackends.none()) {
             return null;
           }
         }
         Node r = getReferencedNode(referenceable);
         if (r == null) {
           return null;
         } else {
           return new IHyperlink[] {new CeylonNodeLink(r, id)};
         }
       }
     }
   }
 }
 static boolean isEmptyPackageDescriptor(CeylonParseController cpc) {
   Tree.CompilationUnit lcu = cpc.getLastCompilationUnit();
   return lcu != null
       && lcu.getUnit() != null
       && lcu.getUnit().getFilename().equals("package.ceylon")
       && lcu.getPackageDescriptors().isEmpty();
 }
 static Tree.CompilationUnit getRootNode(PhasedUnit unit) {
   IEditorPart ce = getCurrentEditor();
   if (ce instanceof CeylonEditor) {
     CeylonEditor editor = (CeylonEditor) ce;
     CeylonParseController cpc = editor.getParseController();
     if (cpc != null) {
       Tree.CompilationUnit rn = cpc.getTypecheckedRootNode();
       if (rn != null) {
         Unit u = rn.getUnit();
         if (u.equals(unit.getUnit())) {
           return rn;
         }
       }
     }
   }
   return unit.getCompilationUnit();
 }
 private Tree.Declaration getSelectionTarget(ITextSelection textSel) {
   CeylonEditor editor = (CeylonEditor) getCurrentEditor();
   CeylonParseController pc = editor.getParseController();
   if (pc == null) {
     return null;
   } else {
     Tree.CompilationUnit ast = pc.getRootNode();
     if (ast == null) {
       return null;
     } else {
       Object sourceNode = findNode(ast, textSel.getOffset());
       if (sourceNode == null) {
         return null;
       } else {
         return getReferencedNode(sourceNode, pc);
       }
     }
   }
 }
 static boolean isModuleDescriptor(CeylonParseController cpc) {
   Tree.CompilationUnit lcu = cpc.getLastCompilationUnit();
   return lcu != null
       && lcu.getUnit() != null
       && lcu.getUnit().getFilename().equals("module.ceylon");
 }
  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 "";
  }
 static boolean isEmptyModuleDescriptor(CeylonParseController cpc) {
   Tree.CompilationUnit lcu = cpc.getLastCompilationUnit();
   return isModuleDescriptor(cpc) && lcu != null && lcu.getModuleDescriptors().isEmpty();
 }
  private boolean terminateWithBrace() throws Exception {
    IDocument doc = editor.getCeylonSourceViewer().getDocument();
    final TextChange change = new DocumentChange("Terminate Statement", doc);
    change.setEdit(new MultiTextEdit());
    CeylonParseController parser = parse();
    CompilationUnit rootNode = parser.getRootNode();
    IRegion li = getLineInfo(doc);
    final String lineText = doc.get(li.getOffset(), li.getLength());
    final List<CommonToken> tokens = parser.getTokens();
    final int startOfCodeInLine = getCodeStart(li, lineText, tokens);
    final int endOfCodeInLine = getCodeEnd(li, lineText, tokens);
    new Processor() {
      @Override
      public void visit(Tree.Expression that) {
        super.visit(that);
        if (that.getStopIndex() <= endOfCodeInLine && that.getStartIndex() >= startOfCodeInLine) {
          Token et = that.getMainEndToken();
          Token st = that.getMainToken();
          if (st != null
              && st.getType() == CeylonLexer.LPAREN
              && (et == null || et.getType() != CeylonLexer.RPAREN)) {
            if (!change.getEdit().hasChildren()) {
              change.addEdit(new InsertEdit(that.getStopIndex() + 1, ")"));
            }
          }
        }
      }

      @Override
      public void visit(Tree.ParameterList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RPAREN, ")");
      }

      public void visit(Tree.IndexExpression that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACKET, "]");
      }

      @Override
      public void visit(Tree.TypeParameterList that) {
        super.visit(that);
        terminate(that, CeylonLexer.LARGER_OP, ">");
      }

      @Override
      public void visit(Tree.TypeArgumentList that) {
        super.visit(that);
        terminate(that, CeylonLexer.LARGER_OP, ">");
      }

      @Override
      public void visit(Tree.PositionalArgumentList that) {
        super.visit(that);
        if (that.getToken().getType() == CeylonLexer.LPAREN) { // for infix function syntax
          terminate(that, CeylonLexer.RPAREN, ")");
        }
      }

      @Override
      public void visit(Tree.NamedArgumentList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.SequenceEnumeration that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.IterableType that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, "}");
      }

      @Override
      public void visit(Tree.Tuple that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACKET, "]");
      }

      @Override
      public void visit(Tree.TupleType that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACKET, "]");
      }

      @Override
      public void visit(Tree.ConditionList that) {
        super.visit(that);
        initiate(that, CeylonLexer.LPAREN, "(");
        // does not really work right:
        terminate(that, CeylonLexer.RPAREN, ")");
      }

      @Override
      public void visit(Tree.ForIterator that) {
        super.visit(that);
        initiate(that, CeylonLexer.LPAREN, "(");
        // does not really work right:
        terminate(that, CeylonLexer.RPAREN, ")");
      }

      @Override
      public void visit(Tree.ImportMemberOrTypeList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.ImportModule that) {
        super.visit(that);
        terminate(that, CeylonLexer.SEMICOLON, ";");
      }

      @Override
      public void visit(Tree.ImportModuleList that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.PackageDescriptor that) {
        super.visit(that);
        terminate(that, CeylonLexer.SEMICOLON, ";");
      }

      @Override
      public void visit(Tree.Body that) {
        super.visit(that);
        terminate(that, CeylonLexer.RBRACE, " }");
      }

      @Override
      public void visit(Tree.StatementOrArgument that) {
        super.visit(that);
        if (
        /*that instanceof Tree.ExecutableStatement &&
        	!(that instanceof Tree.ControlStatement) ||
        that instanceof Tree.AttributeDeclaration ||
        that instanceof Tree.MethodDeclaration ||
        that instanceof Tree.ClassDeclaration ||
        that instanceof Tree.InterfaceDeclaration ||*/
        that instanceof Tree.SpecifiedArgument) {
          terminate(that, CeylonLexer.SEMICOLON, ";");
        }
      }

      private void initiate(Node that, int tokenType, String ch) {
        if (that.getStartIndex() >= startOfCodeInLine && that.getStartIndex() <= endOfCodeInLine) {
          Token et = that.getMainToken();
          if (et == null || et.getType() != tokenType || et.getText().startsWith("<missing ")) {
            if (!change.getEdit().hasChildren()) {
              change.addEdit(new InsertEdit(that.getStartIndex(), ch));
            }
          }
        }
      }

      private void terminate(Node that, int tokenType, String ch) {
        if (that.getStartIndex() >= startOfCodeInLine && that.getStartIndex() <= endOfCodeInLine) {
          Token et = that.getMainEndToken();
          if ((et == null || et.getType() != tokenType) || that.getStopIndex() > endOfCodeInLine) {
            if (!change.getEdit().hasChildren()) {
              change.addEdit(new InsertEdit(min(endOfCodeInLine, that.getStopIndex()) + 1, ch));
            }
          }
        }
      }
    }.visit(rootNode);
    if (change.getEdit().hasChildren()) {
      change.perform(new NullProgressMonitor());
      return true;
    }
    return false;
  }