Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0d9ec8530156
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 55fa7734af83
Choose a head ref
  • 2 commits
  • 1 file changed
  • 2 contributors

Commits on Mar 11, 2018

  1. Add keyword_init option to Struct.new

    For more information, please see feature #11925.
    nomadium committed Mar 11, 2018
    Copy the full SHA
    6746380 View commit details

Commits on Mar 21, 2018

  1. Merge pull request #5061 from nomadium/keyword-arguments-on-struct-new

    Add keyword_init option to Struct.new
    headius authored Mar 21, 2018
    Copy the full SHA
    55fa773 View commit details
Showing with 33 additions and 0 deletions.
  1. +33 −0 core/src/main/java/org/jruby/RubyStruct.java
33 changes: 33 additions & 0 deletions core/src/main/java/org/jruby/RubyStruct.java
Original file line number Diff line number Diff line change
@@ -32,8 +32,11 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.exceptions.RaiseException;
import org.jruby.internal.runtime.methods.DynamicMethod;
@@ -174,6 +177,7 @@ private IRubyObject getByName(String name) {
public static RubyClass newInstance(IRubyObject recv, IRubyObject[] args, Block block) {
String name = null;
boolean nilName = false;
boolean keywordInit = false;
Ruby runtime = recv.getRuntime();

if (args.length > 0) {
@@ -187,7 +191,14 @@ public static RubyClass newInstance(IRubyObject recv, IRubyObject[] args, Block

RubyArray member = runtime.newArray();

if (args[args.length - 1] instanceof RubyHash) {
RubyHash kwArgs = args[args.length - 1].convertToHash();
IRubyObject[] rets = ArgsUtil.extractKeywordArgs(runtime.getCurrentContext(), kwArgs, "keyword_init");
keywordInit = rets[0].isTrue();
}

for (int i = (name == null && !nilName) ? 0 : 1; i < args.length; i++) {
if (i == args.length - 1 && args[i] instanceof RubyHash) break;
member.append(runtime.newSymbol(args[i].asJavaString()));
}

@@ -219,11 +230,13 @@ public static RubyClass newInstance(IRubyObject recv, IRubyObject[] args, Block

newStruct.setInternalVariable("__size__", member.length());
newStruct.setInternalVariable("__member__", member);
newStruct.setInternalVariable("__keyword_init__", keywordInit ? runtime.getTrue() : runtime.getFalse());

newStruct.getSingletonClass().defineAnnotatedMethods(StructMethods.class);

// define access methods.
for (int i = (name == null && !nilName) ? 0 : 1; i < args.length; i++) {
if (i == args.length - 1 && args[i] instanceof RubyHash) break;
final String memberName = args[i].asJavaString();
// if we are storing a name as well, index is one too high for values
final int index = (name == null && !nilName) ? i : i - 1;
@@ -274,6 +287,13 @@ public static IRubyObject newStruct(IRubyObject recv, IRubyObject arg0, IRubyObj
public static IRubyObject members(IRubyObject recv, Block block) {
return RubyStruct.members19(recv, block);
}

@JRubyMethod
public static IRubyObject inspect(IRubyObject recv) {
IRubyObject keywordInit = RubyStruct.getInternalVariable((RubyClass)recv, "__keyword_init__");
if (!keywordInit.isTrue()) return recv.inspect();
return recv.inspect().convertToString().catString("(keyword_init: true)");
}
}

/** Create new Structure.
@@ -332,6 +352,19 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
modify();
checkSize(args.length);

IRubyObject keywordInit = RubyStruct.getInternalVariable(classOf(), "__keyword_init__");

if (keywordInit.isTrue()) {
if (args.length != 1 || !(args[0] instanceof RubyHash)) throw context.runtime.newArgumentError("wrong number of arguments (given " + args.length + ", expected 0)");
RubyHash kwArgs = args[0].convertToHash();
RubyArray __members__ = __member__();
String[] members = Stream.of(__members__.toJavaArray())
.map(o -> RubySymbol.objectToSymbolString(o))
.collect(Collectors.toList())
.toArray(new String[__members__.size()]);
args = ArgsUtil.extractKeywordArgs(context, kwArgs, members);
}

System.arraycopy(args, 0, values, 0, args.length);
Helpers.fillNil(values, args.length, values.length, context.runtime);