Package com.puppetlabs.geppetto.ruby.jruby

Source Code of com.puppetlabs.geppetto.ruby.jruby.JRubyServices$Result

/**
* Copyright (c) 2013 Puppet Labs, Inc. and other contributors, as listed below.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*   Puppet Labs
*/
package com.puppetlabs.geppetto.ruby.jruby;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import java.util.Map;

import com.puppetlabs.geppetto.ruby.PPFunctionInfo;
import com.puppetlabs.geppetto.ruby.PPTypeInfo;
import com.puppetlabs.geppetto.ruby.RubySyntaxException;
import com.puppetlabs.geppetto.ruby.spi.IRubyIssue;
import com.puppetlabs.geppetto.ruby.spi.IRubyParseResult;
import com.puppetlabs.geppetto.ruby.spi.IRubyServices;
import org.jruby.CompatVersion;
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.ast.FCallNode;
import org.jruby.ast.ModuleNode;
import org.jruby.ast.Node;
import org.jruby.lexer.yacc.InputStreamLexerSource;
import org.jruby.lexer.yacc.LexerSource;
import org.jruby.lexer.yacc.SyntaxException;
import org.jruby.parser.ParserConfiguration;
import org.jruby.parser.RubyParser;
import org.jruby.parser.RubyParserPool;
import org.jruby.parser.RubyParserResult;

import com.google.common.collect.Lists;

public class JRubyServices  implements IRubyServices{
 
  /**
   * The number of the first line in a source file.
   */
  private final int startLine = 1;

  /**
   * No idea what this is. Setting to true did not seem to add any information to errors.
   */
  private final boolean extraPositionInfo = false;
 
  /**
   * No idea what this is. Setting to false still reports errors with some source and a caret indicating
   * position.
   */
  private final boolean inlineSource = false;
 
  /**
   * Compatibility of Ruby language version.
   */
  private final CompatVersion rubyVersion = CompatVersion.RUBY1_9;

  /**
   * Holds the JRuby parser result (the AST and any reported issues/errors).
   *
   */
  public static class Result implements IRubyParseResult{
    private List<IRubyIssue> issues;
    private Node AST;

    Result(RubyParserResult parserResult, List<IRubyIssue> issues) {
      this.issues = issues;
      this.AST = parserResult == null ? null : parserResult.getAST();
    }

    /**
     * Returns a list of issues. Will return an empty list if there were no issues.
     * @return
     */
    @Override
    public List<IRubyIssue> getIssues() {
      return issues;
    }

    /**
     * @return the parsed AST, or null in case of errors.
     */
    public Node getAST() {
      return AST;
    }

    @Override
    public boolean hasErrors() {
      if(issues != null)
        for(IRubyIssue issue : issues)
          if(issue.isSyntaxError())
            return true;
      return false;
    }

    @Override
    public boolean hasIssues() {
      return issues != null && issues.size() > 0;
    }

  }

  private ParserConfiguration parserConfiguration;
  private Ruby rubyRuntime;

  /**
   * IOExceptions thrown FileNotFound, and while reading
   * @param file
   * @return
   * @throws IOException
   */
  public IRubyParseResult parse(File file) throws IOException {
    return internalParse(file);
  }
 
  protected Result internalParse(File file) throws IOException {
    if(rubyRuntime == null)
      setUp();
   
    // Set up input
    final List<String> lexerCapture = null; // do not want to record the read text lines
    FileInputStream input = new FileInputStream(file);
    LexerSource source = new InputStreamLexerSource(file.getPath(),
        input, lexerCapture, startLine, extraPositionInfo);

    // Get a parser
    RubyParser parser = RubyParserPool.getInstance().borrowParser(rubyVersion);

    // Create a warnings collector to give to the parser
    RubyParserWarningsCollector warnings = new RubyParserWarningsCollector(rubyRuntime);
    parser.setWarnings(warnings);
    RubyParserResult parserResult = null;
    try {
      parserResult = parser.parse(parserConfiguration, source);
    } catch (SyntaxException e) {
      warnings.syntaxError(e);
    } finally {
      RubyParserPool.getInstance().returnParser(parser);
    }
    return new Result(parserResult, warnings.getIssues());
  }
 
  /**
   * Configure a Ruby Runtime, it is needed for the warnings processor even if we are not
   * going to be running any of the scripts.
   */
  public void setUp() {
    RubyInstanceConfig config = new RubyInstanceConfig();
    config.setCompatVersion(rubyVersion);
    rubyRuntime = Ruby.newInstance(config);
    parserConfiguration = new ParserConfiguration(rubyRuntime,startLine,extraPositionInfo,inlineSource,rubyVersion);
  }
 
  public void tearDown() {
    rubyRuntime = null;
    parserConfiguration = null;
  }
  private static final String[] functionModuleFQN = new String[] { "Puppet", "Parser", "Functions"};
  private static final String functionDefinition = "newfunction";
  @Override
  public List<PPFunctionInfo> getFunctionInfo(File file) throws IOException, RubySyntaxException {
    List<PPFunctionInfo> functions = Lists.newArrayList();
    Result result = internalParse(file);
    if(result.hasErrors())
      throw new RubySyntaxException(result.getIssues());
    RubyModuleFinder finder = new RubyModuleFinder();
    ModuleNode foundModule = finder.findModule(result.getAST(), functionModuleFQN);
    if(foundModule == null)
      return functions;
    // find the function
    FCallNode foundFunction = new RubyFunctionCallFinder().findFuntion(foundModule, functionDefinition);
    if(foundFunction == null)
      return functions;
    Object arguments = new ConstEvaluator().eval(foundFunction.getArgsNode());
    // Result should be a list with a String, and a Map
    if(!(arguments instanceof List))
      return functions;
    List<?> argList = (List<?>)arguments;
    if(argList.size() != 2)
      return functions;
    Object name = argList.get(0);
    if(! (name instanceof String))
      return functions;
    Object hash = argList.get(1);
    if(! (hash instanceof Map<?, ?>))
      return functions;
    Object type = ((Map<?,?>)hash).get("type");
    boolean rValue = "rvalue".equals(type);
   
    Object doc = ((Map<?,?>)hash).get("doc");
    String docString = doc == null ? "" : doc.toString();
    functions.add(new PPFunctionInfo((String)name, rValue, docString));
    return functions;
  }

  @Override
  public List<PPTypeInfo> getTypeInfo(File file) throws IOException, RubySyntaxException {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public boolean isMockService() {
    return false;
  }

  @Override
  public List<PPTypeInfo> getTypePropertiesInfo(File file)
      throws IOException, RubySyntaxException {
    throw new UnsupportedOperationException("Implement this method");
  }

  @Override
  public PPTypeInfo getMetaTypeProperties(File file) throws IOException,
      RubySyntaxException {
    throw new UnsupportedOperationException("Implement this method");
  }

  @Override
  public IRubyParseResult parse(String path, Reader reader)
      throws IOException {
    throw new UnsupportedOperationException("Please implement me");

  }

  @Override
  public List<PPTypeInfo> getTypeInfo(String fileName, Reader reader)
      throws IOException, RubySyntaxException {
    throw new UnsupportedOperationException("Please implement me");
  }

  @Override
  public List<PPFunctionInfo> getFunctionInfo(String fileName, Reader reader) {
    throw new UnsupportedOperationException("Please implement me");
  }

  @Override
  public PPTypeInfo getMetaTypeProperties(String fileName,
      Reader reader) {
    throw new UnsupportedOperationException("Please implement me");
  }

  @Override
  public List<PPTypeInfo> getTypePropertiesInfo(String fileName, Reader reader)
      throws IOException, RubySyntaxException {
    throw new UnsupportedOperationException("Please implement me");
  }

  @Override
  public List<PPFunctionInfo> getLogFunctions(File file) throws IOException,
      RubySyntaxException {
    throw new UnsupportedOperationException("Please implement me");
  }
}
TOP

Related Classes of com.puppetlabs.geppetto.ruby.jruby.JRubyServices$Result

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.