diff --git a/jre_emul/Classes/J2ObjC_common.h b/jre_emul/Classes/J2ObjC_common.h index b8aa006304..2aa7d1ce97 100644 --- a/jre_emul/Classes/J2ObjC_common.h +++ b/jre_emul/Classes/J2ObjC_common.h @@ -22,7 +22,6 @@ #import "J2ObjC_types.h" @class IOSClass; -@protocol JavaLangIterable; #ifndef __has_feature #define __has_feature(x) 0 // Compatibility with non-clang compilers. @@ -93,9 +92,6 @@ NSString *JreStrcat(const char *types, ...); jboolean JreAnnotationEquals(id a1, id a2); jint JreAnnotationHashCode(id a); -NSUInteger JreDefaultFastEnumeration( - id obj, NSFastEnumerationState *state, id __unsafe_unretained *stackbuf); - CF_EXTERN_C_END /*! diff --git a/jre_emul/Classes/J2ObjC_common.m b/jre_emul/Classes/J2ObjC_common.m index acf8493d24..0a89559d8a 100644 --- a/jre_emul/Classes/J2ObjC_common.m +++ b/jre_emul/Classes/J2ObjC_common.m @@ -24,7 +24,6 @@ #import "java/lang/AbstractStringBuilder.h" #import "java/lang/AssertionError.h" #import "java/lang/ClassCastException.h" -#import "java/lang/Iterable.h" #import "java/lang/NullPointerException.h" #import "java/lang/Throwable.h" #import "java/util/logging/Level.h" @@ -32,23 +31,23 @@ #import "objc/runtime.h" id JreThrowNullPointerException() { - @throw create_JavaLangNullPointerException_init(); // NOLINT + @throw create_JavaLangNullPointerException_init(); } void JreThrowClassCastException(id obj, Class cls) { - @throw create_JavaLangClassCastException_initWithNSString_( // NOLINT + @throw create_JavaLangClassCastException_initWithNSString_( [NSString stringWithFormat:@"Cannot cast object of type %@ to %@", [[obj java_getClass] getName], NSStringFromClass(cls)]); } void JreThrowClassCastExceptionWithIOSClass(id obj, IOSClass *cls) { - @throw create_JavaLangClassCastException_initWithNSString_( // NOLINT + @throw create_JavaLangClassCastException_initWithNSString_( [NSString stringWithFormat:@"Cannot cast object of type %@ to %@", [[obj java_getClass] getName], [cls getName]]); } void JreThrowAssertionError(id __unsafe_unretained msg) { - @throw AUTORELEASE([[JavaLangAssertionError alloc] initWithId:[msg description]]); // NOLINT + @throw AUTORELEASE([[JavaLangAssertionError alloc] initWithId:[msg description]]); } void JreFinalize(id self) { @@ -74,7 +73,6 @@ id JreStrongAssignAndConsume(__strong id *pIvar, NS_RELEASES_ARGUMENT id value) // locks for atomic access is consistent with how Apple implements atomic // property accessors, and the hashing used here is inspired by Apple's // implementation: -// NOLINTNEXTLINE // http://www.opensource.apple.com/source/objc4/objc4-532.2/runtime/Accessors.subproj/objc-accessors.mm // Spin locks are unsafe to use on iOS because of the potential for priority // inversion so we use pthread_mutex. @@ -415,31 +413,3 @@ FOUNDATION_EXPORT void JreRelease(id obj) { return [NSString stringWithFormat:@"%@_%d", NSStringFromClass(enumClass.objcClass), ordinal]; } } - -NSUInteger JreDefaultFastEnumeration( - __unsafe_unretained id obj, NSFastEnumerationState *state, - __unsafe_unretained id *stackbuf) { - SEL hasNextSel = sel_registerName("hasNext"); - SEL nextSel = sel_registerName("next"); - __unsafe_unretained id iter = (ARCBRIDGE id) (void *) state->extra[0]; - if (!iter) { - static unsigned long no_mutation = 1; - state->mutationsPtr = &no_mutation; - // The for/in loop could break early so we have no guarantee of being able - // to release the iterator. As long as the current autorelease pool is not - // cleared within the loop, this should be fine. - iter = nil_chk([obj iterator]); - state->extra[0] = (unsigned long) iter; - state->extra[1] = (unsigned long) [iter methodForSelector:hasNextSel]; - state->extra[2] = (unsigned long) [iter methodForSelector:nextSel]; - } - jboolean (*hasNextImpl)(id, SEL) = (jboolean (*)(id, SEL)) state->extra[1]; - id (*nextImpl)(id, SEL) = (id (*)(id, SEL)) state->extra[2]; - NSUInteger objCount = 0; - state->itemsPtr = stackbuf; - if (hasNextImpl(iter, hasNextSel)) { - *stackbuf++ = nextImpl(iter, nextSel); - objCount++; - } - return objCount; -} diff --git a/jre_emul/Classes/java/lang/Iterable.h b/jre_emul/Classes/java/lang/Iterable.h new file mode 100644 index 0000000000..cf1bc55ced --- /dev/null +++ b/jre_emul/Classes/java/lang/Iterable.h @@ -0,0 +1,59 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// Iterable.h +// JreEmulation +// +// Created by kstanger on 8/28/13. +// + +#ifndef _JavaLangIterable_H_ +#define _JavaLangIterable_H_ + +@protocol JavaUtilIterator; + +#include "J2ObjC_header.h" + +@protocol JavaUtilFunctionConsumer; +@protocol JavaUtilIterator; +@protocol JavaUtilSpliterator; + +/** + * Instances of classes that implement this interface can be used with + * the enhanced for loop. + */ +@protocol JavaLangIterable + +- (id)iterator; + +- (void)forEachWithJavaUtilFunctionConsumer:(id)action; + +- (id)spliterator; + +@end + +@interface JavaLangIterable : NSObject < JavaLangIterable > +@end + +J2OBJC_EMPTY_STATIC_INIT(JavaLangIterable) + +J2OBJC_TYPE_LITERAL_HEADER(JavaLangIterable) + +FOUNDATION_EXPORT NSUInteger JreDefaultFastEnumeration( + id obj, NSFastEnumerationState *state, id __unsafe_unretained *stackbuf); + +FOUNDATION_EXPORT void JavaLangIterable_forEachWithJavaUtilFunctionConsumer_(id self, id action); + +FOUNDATION_EXPORT id JavaLangIterable_spliterator(id self); + +#endif // _JavaLangIterable_H_ diff --git a/jre_emul/Classes/java/lang/Iterable.m b/jre_emul/Classes/java/lang/Iterable.m new file mode 100644 index 0000000000..8791127fc1 --- /dev/null +++ b/jre_emul/Classes/java/lang/Iterable.m @@ -0,0 +1,104 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// Iterable.h +// JreEmulation +// +// Created by kstanger on 8/28/13. +// + +#include "java/lang/Iterable.h" + +#include "J2ObjC_source.h" +#include "java/util/Iterator.h" +#include "java/util/Iterator.h" +#include "java/util/Objects.h" +#include "java/util/Spliterator.h" +#include "java/util/Spliterators.h" +#include "java/util/function/Consumer.h" + +#pragma clang diagnostic ignored "-Wprotocol" + +@implementation JavaLangIterable + +- (void)forEachWithJavaUtilFunctionConsumer:(id)action { + JavaLangIterable_forEachWithJavaUtilFunctionConsumer_(self, action); +} + +- (id)spliterator { + return JavaLangIterable_spliterator(self); +} + ++ (const J2ObjcClassInfo *)__metadata { + static J2ObjcMethodInfo methods[] = { + { NULL, "LJavaUtilIterator;", 0x401, -1, -1, -1, 0, -1, -1 }, + { NULL, "V", 0x1, 1, 2, -1, 3, -1, -1 }, + { NULL, "LJavaUtilSpliterator;", 0x1, -1, -1, -1, 4, -1, -1 }, + }; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wobjc-multiple-method-names" + methods[0].selector = @selector(iterator); + methods[1].selector = @selector(forEachWithJavaUtilFunctionConsumer:); + methods[2].selector = @selector(spliterator); + #pragma clang diagnostic pop + static const void *ptrTable[] = { + "()Ljava/util/Iterator;", "forEach", "LJavaUtilFunctionConsumer;", + "(Ljava/util/function/Consumer<-TT;>;)V", "()Ljava/util/Spliterator;", + "Ljava/lang/Object;" }; + static const J2ObjcClassInfo _JavaLangIterable = { + "Iterable", "java.lang", ptrTable, methods, NULL, 7, 0x609, 3, 0, -1, -1, -1, 5, -1 }; + return &_JavaLangIterable; +} + +@end + +void JavaLangIterable_forEachWithJavaUtilFunctionConsumer_(id self, id action) { + JavaUtilObjects_requireNonNullWithId_(action); + for (id __strong t in self) { + [((id) nil_chk(action)) acceptWithId:t]; + } +} + +id JavaLangIterable_spliterator(id self) { + return JavaUtilSpliterators_spliteratorUnknownSizeWithJavaUtilIterator_withInt_([self iterator], 0); +} + +J2OBJC_INTERFACE_TYPE_LITERAL_SOURCE(JavaLangIterable) + +NSUInteger JreDefaultFastEnumeration( + __unsafe_unretained id obj, NSFastEnumerationState *state, + __unsafe_unretained id *stackbuf) { + SEL hasNextSel = @selector(hasNext); + SEL nextSel = @selector(next); + __unsafe_unretained id iter = (ARCBRIDGE id) (void *) state->extra[0]; + if (!iter) { + static unsigned long no_mutation = 1; + state->mutationsPtr = &no_mutation; + // The for/in loop could break early so we have no guarantee of being able + // to release the iterator. As long as the current autorelease pool is not + // cleared within the loop, this should be fine. + iter = nil_chk([obj iterator]); + state->extra[0] = (unsigned long) iter; + state->extra[1] = (unsigned long) [iter methodForSelector:hasNextSel]; + state->extra[2] = (unsigned long) [iter methodForSelector:nextSel]; + } + jboolean (*hasNextImpl)(id, SEL) = (jboolean (*)(id, SEL)) state->extra[1]; + id (*nextImpl)(id, SEL) = (id (*)(id, SEL)) state->extra[2]; + NSUInteger objCount = 0; + state->itemsPtr = stackbuf; + if (hasNextImpl(iter, hasNextSel)) { + *stackbuf++ = nextImpl(iter, nextSel); + objCount++; + } + return objCount; +} diff --git a/jre_emul/android/platform/libcore/ojluni/src/main/java/java/lang/Iterable.java b/jre_emul/android/platform/libcore/ojluni/src/main/java/java/lang/Iterable.java deleted file mode 100644 index 96509f29ee..0000000000 --- a/jre_emul/android/platform/libcore/ojluni/src/main/java/java/lang/Iterable.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package java.lang; - -import com.google.j2objc.NSFastEnumeration; -import java.util.Iterator; -import java.util.Objects; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.Consumer; - -/** - * Implementing this interface allows an object to be the target of - * the "for-each loop" statement. See - * - * For-each Loop - * - * - * @param the type of elements returned by the iterator - * - * @since 1.5 - * @jls 14.14.2 The enhanced for statement - */ -public interface Iterable extends NSFastEnumeration { // J2ObjC modified. - /** - * Returns an iterator over elements of type {@code T}. - * - * @return an Iterator. - */ - Iterator iterator(); - - /** - * Performs the given action for each element of the {@code Iterable} - * until all elements have been processed or the action throws an - * exception. Unless otherwise specified by the implementing class, - * actions are performed in the order of iteration (if an iteration order - * is specified). Exceptions thrown by the action are relayed to the - * caller. - * - * @implSpec - *

The default implementation behaves as if: - *

{@code
-     *     for (T t : this)
-     *         action.accept(t);
-     * }
- * - * @param action The action to be performed for each element - * @throws NullPointerException if the specified action is null - * @since 1.8 - */ - default void forEach(Consumer action) { - Objects.requireNonNull(action); - for (T t : this) { - action.accept(t); - } - } - - /** - * Creates a {@link Spliterator} over the elements described by this - * {@code Iterable}. - * - * @implSpec - * The default implementation creates an - * early-binding - * spliterator from the iterable's {@code Iterator}. The spliterator - * inherits the fail-fast properties of the iterable's iterator. - * - * @implNote - * The default implementation should usually be overridden. The - * spliterator returned by the default implementation has poor splitting - * capabilities, is unsized, and does not report any spliterator - * characteristics. Implementing classes can nearly always provide a - * better implementation. - * - * @return a {@code Spliterator} over the elements described by this - * {@code Iterable}. - * @since 1.8 - */ - default Spliterator spliterator() { - return Spliterators.spliteratorUnknownSize(iterator(), 0); - } -} diff --git a/jre_emul/android/platform/libcore/ojluni/src/main/java/java/lang/Throwable.java b/jre_emul/android/platform/libcore/ojluni/src/main/java/java/lang/Throwable.java index 39991c7002..5387aa86c8 100644 --- a/jre_emul/android/platform/libcore/ojluni/src/main/java/java/lang/Throwable.java +++ b/jre_emul/android/platform/libcore/ojluni/src/main/java/java/lang/Throwable.java @@ -25,9 +25,6 @@ */ package java.lang; - -import com.google.j2objc.NSException; - import java.io.*; import java.util.*; diff --git a/jre_emul/jre_sources.mk b/jre_emul/jre_sources.mk index 34be5a7a07..5f618c1f3d 100644 --- a/jre_emul/jre_sources.mk +++ b/jre_emul/jre_sources.mk @@ -44,6 +44,7 @@ NATIVE_JRE_SOURCES_CORE = \ NSObject+JavaObject.m \ NSString+JavaString.m \ java/lang/AbstractStringBuilder.m \ + java/lang/Iterable.m \ java/lang/reflect/AccessibleObject.m \ java/lang/reflect/Constructor.m \ java/lang/reflect/Executable.m \ @@ -172,7 +173,6 @@ JAVA_PUBLIC_SOURCES_CORE = \ java/lang/Integer.java \ java/lang/InternalError.java \ java/lang/InterruptedException.java \ - java/lang/Iterable.java \ java/lang/LinkageError.java \ java/lang/Long.java \ java/lang/Math.java \ @@ -1810,11 +1810,11 @@ SOURCE_RETENTION_ANNOTATIONS = \ # Java classes with hand written obj-c implementations. Shouldn't be translated, # but need to include the .java file in jre_emul.jar. EMULATED_JAVA_SOURCES = \ - com/google/j2objc/NSException.java \ - com/google/j2objc/NSFastEnumeration.java \ java/lang/AbstractStringBuilder.java \ java/lang/Class.java \ java/lang/Cloneable.java \ + java/lang/Iterable.java \ + java/lang/NSException.java \ java/lang/Number.java \ java/lang/Object.java \ java/lang/String.java \ @@ -1847,6 +1847,7 @@ PUBLIC_NATIVE_HEADERS = \ NSObject+JavaObject.h \ NSString+JavaString.h \ java/lang/AbstractStringBuilder.h \ + java/lang/Iterable.h \ java/lang/reflect/AccessibleObject.h \ java/lang/reflect/Constructor.h \ java/lang/reflect/Executable.h \ diff --git a/jre_emul/stub_classes/com/google/j2objc/NSFastEnumeration.java b/jre_emul/stub_classes/com/google/j2objc/NSFastEnumeration.java deleted file mode 100644 index 22c24945de..0000000000 --- a/jre_emul/stub_classes/com/google/j2objc/NSFastEnumeration.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.j2objc; - -/** - * This stub is mapped to the iOS NSFastEnumeration protocol. We need the Java - * stub class so that java.lang.Iterable instances can support fast enumeration. - */ -public interface NSFastEnumeration { -} diff --git a/jre_emul/stub_classes/java/lang/Iterable.java b/jre_emul/stub_classes/java/lang/Iterable.java new file mode 100644 index 0000000000..9f8c05f0c1 --- /dev/null +++ b/jre_emul/stub_classes/java/lang/Iterable.java @@ -0,0 +1,42 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package java.lang; + +import java.util.Iterator; +import java.util.Spliterator; +import java.util.function.Consumer; + +/** + * Stub implementation of java.lang.Iterable. + * + * @see java.lang.Object + */ +public interface Iterable { + + /** + * Returns an {@link Iterator} for the elements in this object. + * + * @return An {@code Iterator} instance. + */ + Iterator iterator(); + + default void forEach(Consumer action) {} + + default Spliterator spliterator() { + return null; + } +} diff --git a/jre_emul/stub_classes/com/google/j2objc/NSException.java b/jre_emul/stub_classes/java/lang/NSException.java similarity index 97% rename from jre_emul/stub_classes/com/google/j2objc/NSException.java rename to jre_emul/stub_classes/java/lang/NSException.java index b62285c611..8302f0e3ed 100644 --- a/jre_emul/stub_classes/com/google/j2objc/NSException.java +++ b/jre_emul/stub_classes/java/lang/NSException.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.google.j2objc; +package java.lang; /** * This stub is mapped to the iOS NSException class. We need the Java stub class so that diff --git a/translator/src/main/java/com/google/devtools/j2objc/util/TypeUtil.java b/translator/src/main/java/com/google/devtools/j2objc/util/TypeUtil.java index 018a3e2c5e..7742af4e80 100644 --- a/translator/src/main/java/com/google/devtools/j2objc/util/TypeUtil.java +++ b/translator/src/main/java/com/google/devtools/j2objc/util/TypeUtil.java @@ -69,8 +69,6 @@ public final class TypeUtil { GeneratedTypeElement.newIosClass("IOSClass", NS_OBJECT, "IOSClass.h"); public static final TypeElement NS_COPYING = GeneratedTypeElement.newIosInterface("NSCopying", ""); - public static final TypeElement NS_FASTENUMERATION = - GeneratedTypeElement.newIosInterface("NSFastEnumeration", ""); public static final TypeElement IOS_OBJECT_ARRAY = GeneratedTypeElement.newIosClass("IOSObjectArray", NS_OBJECT, "IOSObjectArray.h"); public static final TypeMirror NATIVE_CHAR_PTR = new NativeType("char *"); @@ -124,16 +122,10 @@ public TypeUtil(ParserEnvironment env, ElementUtil elementUtil) { .put(javaNumber, NS_NUMBER) .put(javaCloneable, NS_COPYING); - TypeElement typeNSException = javacElements.getTypeElement("com.google.j2objc.NSException"); - TypeElement typeNSFastEnumeration = - javacElements.getTypeElement("com.google.j2objc.NSFastEnumeration"); - - // Types could be null if the user is not using jre_emul.jar as the boot path. - if (typeNSException != null) { - typeMapBuilder.put(typeNSException, NS_EXCEPTION); - } - if (typeNSFastEnumeration != null) { - typeMapBuilder.put(typeNSFastEnumeration, NS_FASTENUMERATION); + TypeElement javaNSException = javacElements.getTypeElement("java.lang.NSException"); + // Could be null if the user is not using jre_emul.jar as the boot path. + if (javaNSException != null) { + typeMapBuilder.put(javaNSException, NS_EXCEPTION); } javaToObjcTypeMap = typeMapBuilder.build();