Вместо создания копии я предлагаю использовать средство доступа в NSObject, чтобы получить доступ к NSMutableOrderedSet отношений.
- (void)addSubitemsObject:(SubItem *)value {
NSMutableOrderedSet* tempSet = [self mutableOrderedSetValueForKey:@"subitems"];
[tempSet addObject:value];
}
Например, Примечания к выпуску Core Data для iOS v5.0 ссылаются на это.
В коротком тесте это сработало в моем приложении.
Здесь есть пара проблем. Вы можете быть заинтересованы в
зная Java-тип приемника вызова метода или просто
зная, что вызывается класс метода. Информация о Java больше
информативен, поскольку он также дает вам общие типы, например List
в то время как Elements предоставит вам только класс, например List
.
Получение элемента
Чтобы получить элемент класса, для которого вызывается метод, вы можете сделать следующее:
MethodInvocationTree node = ...;
Element method =
TreeInfo.symbol((JCTree)node.getMethodSelect());
TypeElement invokedClass = (TypeElement)method.getEnclosingElement();
Угловые корпуса:
1.
invokedClass может быть суперклассом типа получателя. Так работает
фрагмент new ArrayList
вернет
AbstractList
вместо ArrayList
, поскольку реализовано equals ()
в AbstractList
, а не в ArrayList
.
2.
При обработке вызовов массива, например new int []. Clone ()
, вы должны
get TypeElement
класса Array
.
Получение фактического типа
Чтобы получить тип, нет прямого способа определить, что
Тип ресивера есть. Есть некоторая сложность в обработке вызовов методов
внутри внутренних классов, где получатель не указан явно
(например, в отличие от OuterClass.this.toString ()
). Вот пример реализации:
MethodInvocationTree node = ...;
TypeMirror receiver;
if (methodSel.getKind() == Tree.Kind.MEMBER_SELECT) {
ExpressionTree receiver = ((MemberSelectTree)methodSel).getExpression();
receiverType = ((JCTree)receiver).type;
} else if (methodSel.getKind() == Tree.Kind.IDENTIFIER) {
// need to resolve implicit this, which is described in
// JLS3 15.12.1 and 15.9.2
// A bit too much work that I don't want to work on now
// Look at source code of
// Attr.visitApply(JCMethodInvocation)
// resolveImplicitThis(DiagnosticPosition, Env, Type)
} else
throw new AssertionError("Unexpected type: " + methodSel.getKind());
Примечание:
Тип получателя
должен быть TypeMirror
, а не DeclaredType
К сожалению. При вызове new int [5] .clone ()
, получатель
будет
ArrayType
из int []
, который более информативен, чем предыдущий
метод.
Запуск его
Оба предыдущих метода требуют, чтобы компилятор определил тип
информация для классов. В обычных обстоятельствах компилятор
разрешать только типы для объявлений методов, но не тела.
Следовательно, методы, описанные ранее, вместо этого вернут null
.
Чтобы компилятор разрешил информацию о типе, вы можете выполнить одно из следующими способами:
1.
Используйте класс AbstractTypeProcessor
, который только что был добавлен в
репозиторий компилятора для JDK 7. Ознакомьтесь с работой над JSR
308 и их компилятор.
Хотя работа в основном ведется над аннотированными типами, это может быть полезно для.
Компилятор позволяет использовать предоставленный класс в обратном
совместим с Java 5.
Этот подход позволяет вам писать процессоры, которые вызываются просто как ваши нынешние процессоры.
2.
Используйте вместо него JavacTask
и вызовите JavacTask.analyze ()
. смотреть на
основной метод этого теста javac , чтобы увидеть, как
чтобы вызвать посетителя на классы.
Этот подход делает ваш процессор больше похожим на инструмент анализа а не плагин к компилятору, так как вам нужно будет вызвать его напрямую, а не как обычный процесс.