001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package jet.runtime;
018
019 import jet.Function0;
020
021 import java.util.*;
022
023 @SuppressWarnings("unused")
024 public class Intrinsics {
025 private Intrinsics() {
026 }
027
028 public static String stringPlus(String self, Object other) {
029 return ((self == null) ? "null" : self) + ((other == null) ? "null" : other.toString());
030 }
031
032 public static void throwNpe() {
033 throw new JetNullPointerException();
034 }
035
036 public static void checkReturnedValueIsNotNull(Object value, String className, String methodName) {
037 if (value == null) {
038 IllegalStateException exception =
039 new IllegalStateException("Method specified as non-null returned null: " + className + "." + methodName);
040 throw sanitizeStackTrace(exception);
041 }
042 }
043
044 public static void checkFieldIsNotNull(Object value, String className, String fieldName) {
045 if (value == null) {
046 IllegalStateException exception =
047 new IllegalStateException("Field specified as non-null contains null: " + className + "." + fieldName);
048 throw sanitizeStackTrace(exception);
049 }
050 }
051
052 public static void checkParameterIsNotNull(Object value, String paramName) {
053 if (value == null) {
054 StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
055
056 // #0 is Thread.getStackTrace(), #1 is Intrinsics.checkParameterIsNotNull, #2 is our caller
057 StackTraceElement caller = stackTraceElements[2];
058 String className = caller.getClassName();
059 String methodName = caller.getMethodName();
060
061 IllegalArgumentException exception =
062 new IllegalArgumentException("Parameter specified as non-null contains null: " +
063 "method " + className + "." + methodName +
064 ", parameter " + paramName);
065 throw sanitizeStackTrace(exception);
066 }
067 }
068
069 public static <T> Class<T> getJavaClass(T self) {
070 return (Class<T>) self.getClass();
071 }
072
073 public static int compare(long thisVal, long anotherVal) {
074 return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
075 }
076
077 public static int compare(int thisVal, int anotherVal) {
078 return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
079 }
080
081 public static boolean areEqual(Object first, Object second) {
082 return first == null ? second == null : first.equals(second);
083 }
084
085 public static <R> R stupidSync(Object lock, Function0<R> block) {
086 synchronized (lock) {
087 return block.invoke();
088 }
089 }
090
091 private static final Set<String> METHOD_NAMES_TO_SKIP = new HashSet<String>(Arrays.asList(
092 "throwNpe", "checkReturnedValueIsNotNull", "checkFieldIsNotNull", "checkParameterIsNotNull"
093 ));
094
095 private static <T extends Throwable> T sanitizeStackTrace(T throwable) {
096 StackTraceElement[] stackTrace = throwable.getStackTrace();
097 ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
098 boolean skip = true;
099 for(StackTraceElement ste : stackTrace) {
100 if (!skip) {
101 list.add(ste);
102 }
103 else {
104 if ("jet.runtime.Intrinsics".equals(ste.getClassName())) {
105 if (METHOD_NAMES_TO_SKIP.contains(ste.getMethodName())) {
106 skip = false;
107 }
108 }
109 }
110 }
111 throwable.setStackTrace(list.toArray(new StackTraceElement[list.size()]));
112 return throwable;
113 }
114
115 private static class JetNullPointerException extends NullPointerException {
116 @Override
117 public synchronized Throwable fillInStackTrace() {
118 super.fillInStackTrace();
119 return sanitizeStackTrace(this);
120 }
121 }
122
123 public static class SpreadBuilder extends ArrayList {
124 public void addSpread(Object array) {
125 if (array != null) {
126 if (array instanceof Object[]) {
127 Object[] arr = (Object[]) array;
128 if (arr.length > 0) {
129 ensureCapacity(size() + arr.length);
130 for (int i = 0; i < arr.length; i++) {
131 add(arr[i]);
132 }
133 }
134 }
135 else if (array instanceof Collection) {
136 addAll((Collection) array);
137 }
138 else if (array instanceof Iterable) {
139 for(Iterator iterator = ((Iterable) array).iterator(); iterator.hasNext(); ) {
140 add(iterator.next());
141 }
142 }
143 else if (array instanceof Iterator) {
144 for(Iterator iterator = ((Iterator) array); iterator.hasNext(); ) {
145 add(iterator.next());
146 }
147 }
148 else {
149 throw new UnsupportedOperationException("Don't know how to spread " + array.getClass());
150 }
151 }
152 }
153 }
154 }