/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.compiler.internal.core.validation.part;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.edt.compiler.binding.IRPartBinding;
import org.eclipse.edt.compiler.core.ast.AbstractASTVisitor;
import org.eclipse.edt.compiler.core.ast.Name;
import org.eclipse.edt.compiler.core.ast.Record;
import org.eclipse.edt.compiler.core.ast.SettingsBlock;
import org.eclipse.edt.compiler.core.ast.StructureItem;
import org.eclipse.edt.compiler.internal.core.builder.IProblemRequestor;
import org.eclipse.edt.compiler.internal.core.lookup.ICompilerOptions;
import org.eclipse.edt.compiler.internal.core.validation.ExpressionValidator;
import org.eclipse.edt.compiler.internal.core.validation.annotation.AnnotationValidator;
import org.eclipse.edt.compiler.internal.core.validation.name.EGLNameValidator;
import org.eclipse.edt.compiler.internal.core.validation.statement.FieldValidator;
import org.eclipse.edt.compiler.internal.core.validation.type.TypeValidator;
import org.eclipse.edt.compiler.internal.util.BindingUtil;
import org.eclipse.edt.mof.egl.Field;
import org.eclipse.edt.mof.egl.Type;
public class FlexibleRecordValidator extends AbstractASTVisitor {
protected IProblemRequestor problemRequestor;
IRPartBinding irBinding;
org.eclipse.edt.mof.egl.Record recordBinding;
private Name recordNameNode;
private ICompilerOptions compilerOptions;
public FlexibleRecordValidator(IProblemRequestor problemRequestor, IRPartBinding irBinding, ICompilerOptions compilerOptions) {
this.problemRequestor = problemRequestor;
this.compilerOptions = compilerOptions;
this.irBinding = irBinding;
this.recordBinding = (org.eclipse.edt.mof.egl.Record)irBinding.getIrPart();
}
@Override
public boolean visit(Record record) {
recordNameNode = record.getName();
EGLNameValidator.validate(recordNameNode, EGLNameValidator.RECORD, problemRequestor, compilerOptions);
new AnnotationValidator(problemRequestor, compilerOptions).validateAnnotationTarget(record);
record.accept(new ExpressionValidator(irBinding, problemRequestor, compilerOptions));
return true;
}
@Override
public boolean visit(StructureItem structureItem) {
new AnnotationValidator(problemRequestor, compilerOptions).validateAnnotationTarget(structureItem);
structureItem.accept(new FieldValidator(problemRequestor, compilerOptions, irBinding));
TypeValidator.validateTypeDeclaration(structureItem.getType(), irBinding, problemRequestor);
Type typeBinding = structureItem.getType().resolveType();
if (typeBinding instanceof org.eclipse.edt.mof.egl.Record && containsReferenceTo((org.eclipse.edt.mof.egl.Record)typeBinding, recordBinding, new ArrayList<org.eclipse.edt.mof.egl.Record>())) {
problemRequestor.acceptProblem(
structureItem.getType(),
IProblemRequestor.RECURSIVE_LOOP_STARTED_WITHIN_FLEXIBLE_RECORD_BY_TYPEDEF,
new String[]{typeBinding.getTypeSignature()});
}
return false;
}
@Override
public boolean visit(SettingsBlock settingsBlock) {
return false;
}
private boolean containsReferenceTo(org.eclipse.edt.mof.egl.Record mainRecord, org.eclipse.edt.mof.egl.Record recordToLookFor, List<org.eclipse.edt.mof.egl.Record> processedRecords) {
for (Field f : mainRecord.getFields()) {
Type t = f.getType();
if (t instanceof org.eclipse.edt.mof.egl.Record) {
org.eclipse.edt.mof.egl.Record currentRecord = (org.eclipse.edt.mof.egl.Record)BindingUtil.realize((org.eclipse.edt.mof.egl.Record)t);
if (primContainsReferenceTo(recordToLookFor, processedRecords, currentRecord)) {
return true;
}
}
}
return false;
}
private boolean primContainsReferenceTo(org.eclipse.edt.mof.egl.Record recordToLookFor, List<org.eclipse.edt.mof.egl.Record> processedRecords, org.eclipse.edt.mof.egl.Record currentRecord) {
if (currentRecord.equals(recordToLookFor)) {
return true;
}
if (!processedRecords.contains(currentRecord)) {
processedRecords.add(currentRecord);
if (containsReferenceTo((org.eclipse.edt.mof.egl.Record)currentRecord, recordToLookFor, processedRecords )) {
return true;
}
}
return false;
}
}