/******************************************************************************* * Copyright (c) 2012 Bruno Medeiros and other Contributors. * 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: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package dtool.engine.tests; import static melnorme.utilbox.core.Assert.AssertNamespace.assertFail; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import static melnorme.utilbox.core.CoreUtil.areEqual; import static melnorme.utilbox.misc.StringUtil.collToString; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import melnorme.lang.tooling.ast.SourceElement; import melnorme.lang.tooling.engine.ErrorElement; import melnorme.lang.tooling.engine.intrinsics.CommonLanguageIntrinsics.IPrimitiveDefUnit; import melnorme.lang.tooling.symbols.INamedElement; import java.util.function.Function; import melnorme.utilbox.misc.ArrayUtil; import melnorme.utilbox.misc.CollectionUtil; import melnorme.utilbox.misc.StringUtil; import melnorme.utilbox.tests.CommonTestUtils; import dtool.ast.definitions.DefUnit; import dtool.engine.util.NamedElementUtil; import dtool.sourcegen.AnnotatedSource.MetadataEntry; public class DefUnitResultsChecker extends CommonTestUtils { protected final LinkedList<INamedElement> resultElements; protected final LinkedList<INamedElement> resultStdLibElements = CollectionUtil.createLinkedList(); public DefUnitResultsChecker(Iterable<? extends INamedElement> resultDefUnits) { this.resultElements = CollectionUtil.createLinkedList(resultDefUnits); } public DefUnitResultsChecker removeIgnoredDefUnits(boolean ignoreDummyResults, boolean ignorePrimitives) { removeIgnoredElements(resultElements, ignoreDummyResults, ignorePrimitives, false); return this; } public void removeIgnoredElements(boolean ignoreDummyResults, boolean ignorePrimitives, boolean ignoreIntrinsics) { removeIgnoredElements(resultElements, ignoreDummyResults, ignorePrimitives, ignoreIntrinsics); } public static void removeIgnoredElements(LinkedList<INamedElement> resultDefUnits, boolean ignoreDummyResults, boolean ignorePrimitives) { removeIgnoredElements(resultDefUnits, ignoreDummyResults, ignorePrimitives, false); } public static void removeIgnoredElements(LinkedList<INamedElement> resultDefUnits, boolean ignoreDummy, boolean ignorePrimitives, boolean ignoreInstrinsics) { for (Iterator<INamedElement> iterator = resultDefUnits.listIterator(); iterator.hasNext(); ) { INamedElement defElement = iterator.next(); if(ignoreDummy && (defElement.getName().equals("_dummy") || defElement.getName().endsWith("_ignore"))) { iterator.remove(); } else if(ignorePrimitives && defElement instanceof IPrimitiveDefUnit) { iterator.remove(); } else if(ignoreInstrinsics && defElement.isBuiltinElement()) { iterator.remove(); } else if(defElement instanceof ErrorElement) { iterator.remove(); } } } public DefUnitResultsChecker removeStdLibObjectDefUnits() { resultStdLibElements.addAll(removeStdLibObjectElements(resultElements)); return this; } public static LinkedList<INamedElement> removeStdLibObjectElements(LinkedList<INamedElement> elements) { LinkedList<INamedElement> removedElements = CollectionUtil.createLinkedList(); for (Iterator<INamedElement> iterator = elements.listIterator(); iterator.hasNext(); ) { INamedElement namedElement = iterator.next(); String moduleName = namedElement.getModuleFullName(); if(areEqual(moduleName, "object")) { iterator.remove(); removedElements.add(namedElement); } } return removedElements; } public void simpleCheckResults(String... expectedResults) { removeIgnoredDefUnits(true, true); removeStdLibObjectDefUnits(); checkResults(expectedResults, null); } public void checkResults(String[] expectedResults) { checkResults(expectedResults, null); } public void checkDefaultResults(String[] expectedResults) { removeStdLibObjectDefUnits(); removeIgnoredElements(true, true, false); checkResults(expectedResults, null); } public void checkResults(String[] expectedResults, Map<String, MetadataEntry> markers) { assertNotNull(expectedResults); HashSet<String> expectedResultsDeduplicated = hashSet(expectedResults); for (String expectedTarget : expectedResultsDeduplicated) { if(expectedTarget.startsWith("@") ) { String markerName = expectedTarget.substring(1); MetadataEntry marker = assertNotNull(markers.get(markerName)); DefUnitResultsChecker.removeDefUnitByMarker(resultElements, marker); } else { removeDefUnit(expectedTarget); } } if(!resultElements.isEmpty()) { String resultDefUnitsStr = collToString(strmap(resultElements, CompareDefUnits.fnElementToFullyQualifiedName()), "\n"); System.out.println("--- Unexpected elements ("+resultElements.size()+") : ---\n" + resultDefUnitsStr); } assertTrue(resultElements.isEmpty()); } public void removeDefUnit(String expectedElement) { boolean removed = removeExpectedElement(expectedElement, resultElements); if(removed == false) { removed = removeExpectedElement(expectedElement, resultStdLibElements); } if(removed == false) { System.out.println(" > Not Found: " + expectedElement); assertFail(); // Must find a matching result } } public static boolean removeExpectedElement(String expectedElement, Iterable<INamedElement> iterable) { String moduleName = StringUtil.segmentUntilMatch(expectedElement, "/"); String defUnitModuleQualifiedName = StringUtil.substringAfterMatch(expectedElement, "/"); boolean removed = false; if(moduleName == null ) { for (Iterator<INamedElement> iterator = iterable.iterator(); iterator.hasNext(); ) { INamedElement element = iterator.next(); if(element.getName().equals(expectedElement)) { iterator.remove(); removed = true; } } } else { String expectedFullyTypedQualification = moduleName + (defUnitModuleQualifiedName != null ? "/" + defUnitModuleQualifiedName : ""); for (Iterator<INamedElement> iterator = iterable.iterator(); iterator.hasNext(); ) { INamedElement element = iterator.next(); String defUnitTypedQualification = NamedElementUtil.getElementTypedLabel(element); if(defUnitTypedQualification.equals(expectedFullyTypedQualification)) { iterator.remove(); removed = true; } else { continue; // Not a match } } } return removed; } /* ------ */ public static <T> String[] strmap(Collection<T> coll, Function<? super T, String> evalFunction) { return ArrayUtil.map(coll, evalFunction, String.class); } public static void removeDefUnitByMarker(Collection<INamedElement> resolvedDefUnits, MetadataEntry marker) { for (Iterator<INamedElement> iterator = resolvedDefUnits.iterator(); iterator.hasNext(); ) { INamedElement element = iterator.next(); if(element instanceof DefUnit) { DefUnit defNode = (DefUnit) element; if(defNode.defName.getEndPos() == marker.offset || defNode.defName.getStartPos() == marker.offset) { iterator.remove(); return; } } } assertFail(); } public void checkNamedElements(String... expectedResults) { removeStdLibObjectElements(resultElements); removeIgnoredElements(resultElements, true, true, true); @SuppressWarnings("unused") String resultsString = StringUtil.toString(resultElements, "\n", new Function<INamedElement, String>() { @Override public String apply(INamedElement obj) { if(obj instanceof SourceElement) { return NamedElementUtil.getElementTypedLabel(obj, true); } return obj.toString(); } }); for(String expectedLabel : expectedResults) { if(removedNamedElement(expectedLabel)) { continue; } assertFail("Not found: " + expectedLabel); } } protected boolean removedNamedElement(String expectedLabel) { for (Iterator<INamedElement> iterator = resultElements.listIterator(); iterator.hasNext(); ) { INamedElement namedElement = iterator.next(); if(matchesLabel(namedElement, expectedLabel)) { iterator.remove(); return true; } } return false; } public static boolean matchesLabel(INamedElement element, String expectedLabel) { if(expectedLabel == null) { return (element == null); } assertNotNull(element); String elementLabel; if(expectedLabel.startsWith("$")) { elementLabel = "$" + NamedElementUtil.getElementTypedLabel(element, true); } else { elementLabel = NamedElementUtil.namedElementToString(element); } return areEqual(elementLabel, expectedLabel); } }