diff options
| author | Andrew Johnson | 2019-11-14 22:01:55 +0000 |
|---|---|---|
| committer | Andrew Johnson | 2019-11-15 15:35:49 +0000 |
| commit | aab9340edd819746ee4ad5506d4a8ebb1e1f0082 (patch) | |
| tree | bcebc6687769721a67c9fe79de75c5e8dd0b434d | |
| parent | 4d93284448475171f903be4892cb5f40bdfd0768 (diff) | |
| download | org.eclipse.mat-aab9340edd819746ee4ad5506d4a8ebb1e1f0082.tar.gz org.eclipse.mat-aab9340edd819746ee4ad5506d4a8ebb1e1f0082.tar.xz org.eclipse.mat-aab9340edd819746ee4ad5506d4a8ebb1e1f0082.zip | |
552879: OQL enhancements for sub-selects, maps, context providers
return HashMap entry objects for map to array conversion
Also tidy up HTML output with OQL, and more collections
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=552879
Change-Id: Id7d2446513872b48fc61ebc2f9fa9d69160764a9
9 files changed, 125 insertions, 37 deletions
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/collections/HashEntriesQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/collections/HashEntriesQuery.java index 3d27ab6a..a9620241 100644 --- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/collections/HashEntriesQuery.java +++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/collections/HashEntriesQuery.java @@ -328,9 +328,9 @@ public class HashEntriesQuery implements IQuery if (me instanceof IObject)
{
IObject meObject = (IObject) me;
- int keyId = (me.getKey() != null) ? me.getKey().getObjectId() : 0;
- int valueId = (me.getValue() != null) ? me.getValue().getObjectId() : 0;
- e = new Entry(meObject.getObjectId(), meObject.getDisplayName(), keyId, valueId);
+ int keyId = (me.getKey() != null) ? me.getKey().getObjectId() : -1;
+ int valueId = (me.getValue() != null) ? me.getValue().getObjectId() : -1;
+ e = new Entry(obj.getObjectId(), obj.getDisplayName(), keyId, valueId);
}
else
{
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java index 8cde40a5..c5345348 100644 --- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java +++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java @@ -155,6 +155,8 @@ public class KnownCollectionInfo implements ICollectionExtractorProvider new CollectionExtractionInfo("java.lang.ThreadLocal$ThreadLocalMap", // //$NON-NLS-1$ new HashMapCollectionExtractor("size", "table", "referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ new CollectionExtractionInfo("java.lang.ProcessEnvironment$CheckedEntrySet", new WrapperMapExtractor("s")), //$NON-NLS-1$ //$NON-NLS-2$ + new CollectionExtractionInfo("java.lang.ProcessEnvironment$CheckedKeySet", new WrapperMapExtractor("s")), //$NON-NLS-1$ //$NON-NLS-2$ + new CollectionExtractionInfo("java.lang.ProcessEnvironment$CheckedValues", new WrapperMapExtractor("c")), //$NON-NLS-1$ //$NON-NLS-2$ new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$Segment", new HashMapCollectionExtractor("count", "table", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ @@ -243,9 +245,12 @@ public class KnownCollectionInfo implements ICollectionExtractorProvider new CollectionExtractionInfo("sun.util.PreHashedMap", new NoContentCollectionExtractor()), //$NON-NLS-1$ new CollectionExtractionInfo("sun.misc.SoftCache", new NoContentCollectionExtractor()), //$NON-NLS-1$ + new CollectionExtractionInfo("java.util.AbstractMap$2", new ValuesCollectionExtractor("this$0")),//$NON-NLS-1$ //$NON-NLS-2$ + // usually shouldn't match new CollectionExtractionInfo("java.util.AbstractList", new NoContentCollectionExtractor()), //$NON-NLS-1$ new CollectionExtractionInfo("java.util.AbstractMap", new NoContentCollectionExtractor()), //$NON-NLS-1$ - new CollectionExtractionInfo("java.util.AbstractMap$2", new ValuesCollectionExtractor("this$0")),//$NON-NLS-1$ //$NON-NLS-2$ + new CollectionExtractionInfo("java.util.AbstractSet", new NoContentCollectionExtractor()), //$NON-NLS-1$ + new CollectionExtractionInfo("java.util.AbstractCollection", new NoContentCollectionExtractor()), //$NON-NLS-1$ }; } diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/MapCollectionExtractorBase.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/MapCollectionExtractorBase.java index 2e794697..b9506563 100644 --- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/MapCollectionExtractorBase.java +++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/MapCollectionExtractorBase.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2015 SAP AG, IBM Corporation and others + * Copyright (c) 2008, 2019 SAP AG, 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 @@ -80,7 +80,7 @@ public abstract class MapCollectionExtractorBase implements IMapExtractor try { IObject obj = snapshot.getObject(ids[idx++]); - return new EntryObject(coll, getEntryKey(obj), getEntryValue(obj)); + return new EntryObject(obj, getEntryKey(obj), getEntryValue(obj)); } catch (SnapshotException e) { diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/SingletonMapExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/SingletonMapExtractor.java index 1dfe9bfa..9e727270 100644 --- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/SingletonMapExtractor.java +++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/SingletonMapExtractor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2015 SAP AG, IBM Corporation and others + * Copyright (c) 2008, 2019 SAP AG, 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 @@ -89,8 +89,8 @@ public class SingletonMapExtractor implements IMapExtractor public Iterator<Entry<IObject, IObject>> extractMapEntries(IObject coll) throws SnapshotException { - return Collections.singletonMap((IObject) coll.resolveValue(keyField), (IObject) coll.resolveValue(valueField)) - .entrySet().iterator(); + return Collections.singleton((Entry<IObject, IObject>)(new EntryObject(coll, (IObject) coll.resolveValue(keyField), (IObject) coll.resolveValue(valueField)))) + .iterator(); } public boolean hasFillRatio() diff --git a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties index 3f475f43..2dfe35bc 100644 --- a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties +++ b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties @@ -100,7 +100,7 @@ OQLQueryImpl_CheckingClass=Checking class {0} OQLQueryImpl_CollectingObjects=Collecting objects of classes
OQLQueryImpl_Error_CannotCalculateRetainedSet=Cannot calculate retained set on {0}
OQLQueryImpl_Error_ClassCastExceptionOccured=ClassCastException occurred. Remember: sub queries with the modifier INSTANCEOF or without the modifier OBJECTS must return only class objects.
-OQLQueryImpl_Error_ElementIsNotClass=Element is not a class: {0}
+OQLQueryImpl_Error_ElementIsNotClass=Element is not a class: Query: FROM {0} Type: {1}
OQLQueryImpl_Error_InvalidClassNamePattern=Invalid class name pattern {0}
OQLQueryImpl_Error_MissingSnapshot=Missing snapshot
OQLQueryImpl_Error_MustReturnObjectList=Sub-Select must return an object list: {0}
diff --git a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/oql/OQLQueryImpl.java b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/oql/OQLQueryImpl.java index a9e8fa8e..46495331 100644 --- a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/oql/OQLQueryImpl.java +++ b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/oql/OQLQueryImpl.java @@ -1362,7 +1362,10 @@ public class OQLQueryImpl implements IOQLQuery for (IntIterator iter = baseSet.iterator(); iter.hasNext();)
{
int id = iter.nextInt();
- IClass subjectClass = (IClass) ctx.getSnapshot().getObject(id);
+ IObject o = ctx.getSnapshot().getObject(id);
+ if (!(o instanceof IClass))
+ throw new SnapshotException(Messages.OQLQueryImpl_Error_ClassCastExceptionOccured);
+ IClass subjectClass = (IClass)o;
classes.add(subjectClass);
if (query.getFromClause().includeSubClasses())
{
@@ -1586,7 +1589,11 @@ public class OQLQueryImpl implements IOQLQuery }
else if (obj instanceof Integer)
{
- IClass subjectClass = (IClass) this.ctx.getSnapshot().getObject(((Integer) obj).intValue());
+ IObject o = this.ctx.getSnapshot().getObject(((Integer) obj).intValue());
+ if (!(o instanceof IClass))
+ throw new SnapshotException(MessageUtil.format(Messages.OQLQueryImpl_Error_ElementIsNotClass,
+ query.getFromClause().toString(), o.getClass().getName()));
+ IClass subjectClass = (IClass)o;
classes.add(subjectClass);
if (query.getFromClause().includeSubClasses())
{
@@ -1597,7 +1604,11 @@ public class OQLQueryImpl implements IOQLQuery {
for (int id : (int[]) obj)
{
- IClass subjectClass = (IClass) this.ctx.getSnapshot().getObject(id);
+ IObject o = this.ctx.getSnapshot().getObject(id);
+ if (!(o instanceof IClass))
+ throw new SnapshotException(MessageUtil.format(Messages.OQLQueryImpl_Error_ElementIsNotClass,
+ query.getFromClause().toString(), o.getClass().getName()));
+ IClass subjectClass = (IClass)o;
classes.add(subjectClass);
if (query.getFromClause().includeSubClasses())
{
@@ -1605,7 +1616,7 @@ public class OQLQueryImpl implements IOQLQuery }
}
}
- else
+ else if (obj instanceof IClass)
{
IClass subjectClass = (IClass) obj;
classes.add(subjectClass);
@@ -1614,6 +1625,10 @@ public class OQLQueryImpl implements IOQLQuery classes.addAll(subjectClass.getAllSubclasses());
}
}
+ else
+ {
+ throw new SnapshotException(MessageUtil.format(Messages.OQLQueryImpl_Error_ElementIsNotClass, query.getFromClause().toString(), obj.getClass().getName()));
+ }
}
}
else if (result.getClass().isArray())
@@ -1628,7 +1643,11 @@ public class OQLQueryImpl implements IOQLQuery }
else if (obj instanceof Integer)
{
- IClass subjectClass = (IClass) this.ctx.getSnapshot().getObject(((Integer) obj).intValue());
+ IObject o = this.ctx.getSnapshot().getObject(((Integer) obj).intValue());
+ if (!(o instanceof IClass))
+ throw new SnapshotException(MessageUtil.format(Messages.OQLQueryImpl_Error_ElementIsNotClass,
+ query.getFromClause().toString(), o.getClass().getName()));
+ IClass subjectClass = (IClass)o;
classes.add(subjectClass);
if (query.getFromClause().includeSubClasses())
{
@@ -1647,7 +1666,7 @@ public class OQLQueryImpl implements IOQLQuery }
}
}
- else
+ else if (obj instanceof IClass)
{
IClass subjectClass = (IClass) obj;
classes.add(subjectClass);
@@ -1656,9 +1675,13 @@ public class OQLQueryImpl implements IOQLQuery classes.addAll(subjectClass.getAllSubclasses());
}
}
+ else
+ {
+ throw new SnapshotException(MessageUtil.format(Messages.OQLQueryImpl_Error_ElementIsNotClass, query.getFromClause().toString(), obj.getClass().getName()));
+ }
}
}
- else
+ else if (result instanceof IClass)
{
IClass subjectClass = (IClass) result;
classes.add(subjectClass);
@@ -1667,11 +1690,15 @@ public class OQLQueryImpl implements IOQLQuery classes.addAll(subjectClass.getAllSubclasses());
}
}
+ else
+ {
+ throw new SnapshotException(MessageUtil.format(Messages.OQLQueryImpl_Error_ElementIsNotClass, query.getFromClause().toString(), result.getClass().getName()));
+ }
}
catch (ClassCastException e)
{
throw new SnapshotException(MessageUtil.format(Messages.OQLQueryImpl_Error_ElementIsNotClass,
- new Object[] { e.getMessage() }), e);
+ query.getFromClause().toString(), e.getMessage()), e);
}
return filterClasses(listener, classes);
diff --git a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/HtmlOutputter.java b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/HtmlOutputter.java index 8d701ecb..3b4bdb49 100644 --- a/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/HtmlOutputter.java +++ b/plugins/org.eclipse.mat.report/src/org/eclipse/mat/report/internal/HtmlOutputter.java @@ -1,5 +1,5 @@ /*******************************************************************************
- * Copyright (c) 2008, 2013 SAP AG and IBM Corporation.
+ * Copyright (c) 2008, 2019 SAP AG and IBM Corporation.
* 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
@@ -31,6 +31,7 @@ import org.eclipse.mat.query.refined.RefinedStructuredResult; import org.eclipse.mat.query.refined.RefinedTable;
import org.eclipse.mat.query.refined.RefinedTree;
import org.eclipse.mat.query.refined.TotalsRow;
+import org.eclipse.mat.query.registry.Converters;
import org.eclipse.mat.query.registry.QueryObjectLink;
import org.eclipse.mat.query.results.DisplayFileResult;
import org.eclipse.mat.query.results.TextResult;
@@ -457,9 +458,13 @@ public class HtmlOutputter implements IOutputter label = HTMLUtils.escapeText(label);
if (columnIndex == 0)
- renderLink(context, artefact, structured, row, label);
+ renderLink(context, artefact, structured, row, label, columns, columnIndex);
else
- artefact.append(label);
+ {
+ // Is there a context corresponding to this column
+ if (!renderLink(context, artefact, structured, row, label,columns, columnIndex))
+ artefact.append(label);
+ }
}
if (decorator != null)
@@ -488,11 +493,12 @@ public class HtmlOutputter implements IOutputter }
@SuppressWarnings("nls")
- private void renderLink(Context context, Writer artefact, IStructuredResult thing, Object row, String label)
+ private boolean renderLink(Context context, Writer artefact, IStructuredResult thing, Object row, String label, Column columns[], int columnIndex)
throws IOException
{
IContextObject ctx = thing.getContext(row);
- renderContext(context, label, null, ctx, artefact);
+ if (columnIndex == 0)
+ renderContext(context, label, null, ctx, artefact);
boolean first = true;
boolean done = false;
for (ContextProvider prov : thing.getResultMetaData().getContextProviders())
@@ -500,6 +506,17 @@ public class HtmlOutputter implements IOutputter IContextObject ctx1 = prov.getContext(row);
if (moreContextObjects(ctx, ctx1))
{
+ if (columnIndex == 0)
+ {
+ int c;
+ for (c = 1; c < columns.length; ++c)
+ if (columns[c].getLabel().equals(prov.getLabel()))
+ break;
+ if (c < columns.length)
+ continue;
+ }
+ else if (!columns[columnIndex].getLabel().equals(prov.getLabel()))
+ continue;
if (first)
{
first = false;
@@ -507,17 +524,26 @@ public class HtmlOutputter implements IOutputter //artefact.append("<ul>");
done = true;
}
- artefact.append("<br>");
- //artefact.append("<li>");
- String contextLabel = HTMLUtils.escapeText(prov.getLabel());
- renderContext(context, contextLabel, prov.getIcon(), ctx1, artefact);
- //artefact.append("</li>");
+ if (columnIndex == 0)
+ {
+ artefact.append("<br>");
+ //artefact.append("<li>");
+ String contextLabel = HTMLUtils.escapeText(prov.getLabel());
+ renderContext(context, contextLabel, prov.getIcon(), ctx1, artefact);
+ //artefact.append("</li>");
+ }
+ else
+ {
+ // Other column, so render label with the link
+ renderContext(context, label, prov.getIcon(), ctx1, artefact);
+ }
}
}
if (done)
{
//artefact.append("</ul>");
}
+ return done;
}
@SuppressWarnings("nls")
@@ -566,16 +592,19 @@ public class HtmlOutputter implements IOutputter {
IContextObjectSet set = (IContextObjectSet)ctx;
String oqlCommand = set.getOQL();
+ boolean complexoql = oqlCommand != null && !oqlCommand.matches("SELECT . FROM");
int objs[] = set.getObjectIds();
- if (objs.length > 0)
+ // At least one object, and not a single object the same as the base context
+ if (objs.length > 0 && (complexoql || !(objs.length == 1 && objs[0] == objectId)))
{
int n = Math.min(maxLinkObjects, objs.length);
- if (objs.length > n && oqlCommand != null)
+ if (objs.length > n && oqlCommand != null || complexoql)
{
artefact.append("<br><a href=\"");
StringBuilder sb = new StringBuilder("oql");
sb.append(" ");
- sb.append('"').append(oqlCommand).append('"');
+ String escapedCommand = Converters.convertAndEscape(String.class, oqlCommand);
+ sb.append(escapedCommand);
artefact.append(QueryObjectLink.forQuery(sb.toString())).append("\">");
artefact.append(Messages.HtmlOutputter_Label_AllObjects);
artefact.append("</a>");
diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java index 885bcdec..548d979f 100644 --- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java +++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java @@ -1,5 +1,5 @@ /*******************************************************************************
- * Copyright (c) 2014, 2018 IBM Corporation
+ * Copyright (c) 2014, 2019 IBM Corporation
* 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
@@ -526,7 +526,7 @@ public class CreateCollectionDump }
if (added == 0 && (mn == null || c == null))
{
- System.out.println("Missing collection "+cn0+" "+useEmpty());
+ System.out.println("Missing collection "+cn0+" empty="+useEmpty());
}
}
collections = cols.toArray(new Collection[cols.size()]);
@@ -779,6 +779,7 @@ public class CreateCollectionDump "java.util.Hashtable",
"java.util.IdentityHashMap",
"java.util.LinkedHashMap",
+ "java.lang.ProcessBuilder environment",
"javax.print.attribute.standard.PrinterStateReasons",
"java.util.Properties",
"java.security.Provider",
@@ -863,7 +864,21 @@ public class CreateCollectionDump else
{
Method method = cm.getMethod(mn, cons[j]);
- cl = (Map)method.invoke(null, args[j]);
+ Object obj2;
+ if (Modifier.isStatic(method.getModifiers()))
+ {
+ obj2 = null;
+ cl = (Map)method.invoke(obj2, args[j]);
+ }
+ else
+ {
+ // String array constructor of base class
+ Constructor<?>cons2 = cm.getConstructor(String[].class);
+ String args2[] = new String[]{"command"};
+ obj2 = cons2.newInstance(new Object[] {args2});
+ cl = (Map)method.invoke(obj2, args[j]);
+ cl.clear();
+ }
c = cl.getClass();
if (!c.getName().equals(cn))
{
@@ -871,7 +886,9 @@ public class CreateCollectionDump cn = c.getName();
fillValues(cn);
args = buildArgs(mapVals, enumVals);
- cl = (Map)method.invoke(null, args[j]);
+ cl = (Map)method.invoke(obj2, args[j]);
+ if (obj2 != null)
+ cl.clear();
c = cl.getClass();
}
}
@@ -977,6 +994,7 @@ public class CreateCollectionDump }
catch (IllegalArgumentException e)
{
+ e.printStackTrace();
}
catch (InvocationTargetException e)
{
@@ -984,7 +1002,7 @@ public class CreateCollectionDump }
if (added == 0 && (mn == null || c == null))
{
- System.out.println("Missing map "+cn0+" "+useEmpty());
+ System.out.println("Missing map "+cn0+" empty="+useEmpty());
}
}
maps = ms.toArray(new Map[ms.size()]);
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/util/QueryContextMenu.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/util/QueryContextMenu.java index f3c2f23f..645c5b7d 100644 --- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/util/QueryContextMenu.java +++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/util/QueryContextMenu.java @@ -682,7 +682,16 @@ public class QueryContextMenu else
{
// This can be expensive, so don't get it earlier
- int os[] = icos.getObjectIds();
+ int os[];
+ try
+ {
+ os = icos.getObjectIds();
+ }
+ catch (RuntimeException e)
+ {
+ // For example a OQL select query can fail
+ return false;
+ }
inspected += os.length;
if (inspected >= limit)
return false;
|
