blob: fea3d8a3d8d825dbefda588ce635f299bc881201 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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.
*/
package org.jetbrains.jps.builders.java.dependencyView;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataInputOutputUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.org.objectweb.asm.Type;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
/**
* @author: db
* Date: 01.02.11
*/
class MethodRepr extends ProtoMember {
interface Predicate {
boolean satisfy(MethodRepr m);
}
public final TypeRepr.AbstractType[] myArgumentTypes;
public final Set<TypeRepr.AbstractType> myExceptions;
public abstract class Diff extends Difference {
public abstract Specifier<TypeRepr.AbstractType> exceptions();
public abstract boolean defaultAdded();
public abstract boolean defaultRemoved();
}
@Override
public Difference difference(final Proto past) {
final Difference diff = super.difference(past);
final Difference.Specifier<TypeRepr.AbstractType> excs = Difference.make(((MethodRepr)past).myExceptions, myExceptions);
return new Diff() {
@Override
public int addedModifiers() {
return diff.addedModifiers();
}
@Override
public int removedModifiers() {
return diff.removedModifiers();
}
@Override
public boolean no() {
return base() == NONE && !defaultAdded() && !defaultRemoved() && excs.unchanged();
}
@Override
public boolean defaultAdded() {
return hasValue() && !((MethodRepr)past).hasValue();
}
@Override
public boolean defaultRemoved() {
return !hasValue() && ((MethodRepr)past).hasValue();
}
@Override
public Specifier<TypeRepr.AbstractType> exceptions() {
return excs;
}
@Override
public int base() {
return diff.base();
}
@Override
public boolean packageLocalOn() {
return diff.packageLocalOn();
}
@Override
public boolean hadValue() {
return ((MethodRepr)past).hasValue();
}
@Override
public boolean weakedAccess() {
return diff.weakedAccess();
}
};
}
public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
myType.updateClassUsages(context, owner, s);
for (int i = 0; i < myArgumentTypes.length; i++) {
myArgumentTypes[i].updateClassUsages(context, owner, s);
}
if (myExceptions != null) {
for (TypeRepr.AbstractType typ : myExceptions) {
typ.updateClassUsages(context, owner, s);
}
}
}
public MethodRepr(final DependencyContext context,
final int a,
final int n,
final int s,
final String d,
final String[] e,
final Object value) {
super(a, s, n, TypeRepr.getType(context, Type.getReturnType(d)), value);
Set<TypeRepr.AbstractType> typeCollection =
e != null ? new THashSet<TypeRepr.AbstractType>(e.length) : Collections.<TypeRepr.AbstractType>emptySet();
myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, e, typeCollection);
myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(d));
}
public MethodRepr(final DependencyContext context, final DataInput in) {
super(context, in);
try {
final DataExternalizer<TypeRepr.AbstractType> externalizer = TypeRepr.externalizer(context);
final int size = DataInputOutputUtil.readINT(in);
myArgumentTypes = RW.read(externalizer, in, new TypeRepr.AbstractType[size]);
myExceptions = (Set<TypeRepr.AbstractType>)RW.read(externalizer, new THashSet<TypeRepr.AbstractType>(0), in);
}
catch (IOException e) {
throw new BuildDataCorruptedException(e);
}
}
@Override
public void save(final DataOutput out) {
super.save(out);
RW.save(myArgumentTypes, out);
RW.save(myExceptions, out);
}
public static DataExternalizer<MethodRepr> externalizer(final DependencyContext context) {
return new DataExternalizer<MethodRepr>() {
@Override
public void save(@NotNull final DataOutput out, final MethodRepr value) throws IOException {
value.save(out);
}
@Override
public MethodRepr read(@NotNull DataInput in) throws IOException {
return new MethodRepr(context, in);
}
};
}
static Predicate equalByJavaRules(final MethodRepr me) {
return new Predicate() {
@Override
public boolean satisfy(MethodRepr that) {
if (me == that) return true;
return me.name == that.name && Arrays.equals(me.myArgumentTypes, that.myArgumentTypes);
}
};
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final MethodRepr that = (MethodRepr)o;
return name == that.name && myType.equals(that.myType) && Arrays.equals(myArgumentTypes, that.myArgumentTypes);
}
@Override
public int hashCode() {
return 31 * (31 * Arrays.hashCode(myArgumentTypes) + myType.hashCode()) + name;
}
private String getDescr(final DependencyContext context) {
final StringBuilder buf = new StringBuilder();
buf.append("(");
for (TypeRepr.AbstractType t : myArgumentTypes) {
buf.append(t.getDescr(context));
}
buf.append(")");
buf.append(myType.getDescr(context));
return buf.toString();
}
public UsageRepr.Usage createUsage(final DependencyContext context, final int owner) {
return UsageRepr.createMethodUsage(context, name, owner, getDescr(context));
}
public UsageRepr.Usage createMetaUsage(final DependencyContext context, final int owner) {
return UsageRepr.createMetaMethodUsage(context, name, owner, getDescr(context));
}
@Override
public void toStream(final DependencyContext context, final PrintStream stream) {
super.toStream(context, stream);
stream.print(" Arguments : ");
for (TypeRepr.AbstractType t : myArgumentTypes) {
stream.print(t.getDescr(context));
stream.print("; ");
}
stream.println();
final TypeRepr.AbstractType[] es = myExceptions.toArray(new TypeRepr.AbstractType[myExceptions.size()]);
Arrays.sort(es, new Comparator<TypeRepr.AbstractType>() {
@Override
public int compare(final TypeRepr.AbstractType o1, final TypeRepr.AbstractType o2) {
return o1.getDescr(context).compareTo(o2.getDescr(context));
}
});
stream.print(" Exceptions : ");
for (final TypeRepr.AbstractType e : es) {
stream.print(e.getDescr(context));
stream.print("; ");
}
stream.println();
}
}