function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ken KoellnerKen Koellner 

How to tell if a field is references in Apex

We'd like to check if about 200 fields are referenced anywhere in code-- Apex, VF, workflows, trigger.  Text searches really don't cut it as you could have a field such as MyCustomField__c in more than one object.  So without doing the same symbol-table work a compiler would do, with references like myObj1.MyCustomField__c and myObj2.MyCustomField__c you would not know the objec type.

I thought of a way to do it via validation but it does not appear to be working.  The idea I had is --

create a package.xml with no types.
create a destructiveChanges.xml with CustomField entries for the custom fields.

But one the descructiveChanges.xml field has one field I know is reference and a I run a validation with the ant deployment tool, I get a successful validation.

Anyone know why the validation could succeed even with a reference to the field in Apex?

Anyone know any other method that is 100% realiable and understands the object and field name together (no simple text searches)?

 
Alain CabonAlain Cabon
Hi, 

I tried to solve the same problem and I found three techniques:

1) APEX: https://github.com/regularcoder/deepfield

https://github.com/regularcoder/deepfield/blob/master/classes/DeepFieldController.cls
//Get apex classes where field is used
    public List<String> getClassUsage() { 
        List<String> retVal = new List<String>();
        
        String response = getHTTP('/services/data/v37.0/tooling/search/?q=FIND+{' + currentobject + '+AND+' + currentfield + '}+IN+ALL+FIELDS+RETURNING+ApexClass+(Name)');
        
        retVal.add(response);
        
        return retVal;
    }


2) JAVA: Deleting the custom fields with AllOrNoneHeader=true and at least one field among ten in the array that I am sure it is not deletable because it is used in some Apex code (+ a new empty sandbox by copy, zero risk) for getting the messages of errors (undeletable fields) which are full of informations about the used fields. I often used this technique.

Starting in API version 34.0, this call supports the AllOrNoneHeader header. By default, if the AllOrNoneHeader isn’t used in any API version, this call can delete a partial set of records for records with no errors (equivalent to AllOrNoneHeader=false). If AllOrNoneHeader is set to true, no records are deleted if one or more records cause a failure.

https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_deleteMetadata.htm?search_text=delete

3) TOOLING:  the symbol tables 

Use symbol tables instead of building a parser or compiler. Symbol tables allow you to do symbol highlighting, code navigation, code completion, symbol searches, and more.
A symbol table can’t be created if the content referenced by the ContentEntityId field doesn’t use a symbol table. Compiler errors for the last deployment of the MetadataContainer in the MetadataContainerId field also prevent a symbol table from being created.

https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_symboltable.htm

The expert of the symbol table should be Daniel Ballinger from New-Zealand.

https://developer.salesforce.com/forums/?id=906F0000000MISBIA4

Regards.
Ken KoellnerKen Koellner
All interesting ideas.  I hope I find time to delve into them if for nothing more than my on edification.

Our goal is to determine if field are deletable.  I did find away to accomplish what we wanted to and it's simple.

Create an empty package.xml.
Create a destructiveChanges.xml withe the approproate members in the CustomField type.
Do a retrieve.
Do a validation.

You then get validation errors for fields that can't be deleted.  You only get one per field but that's enough for our purposes.
Eric PepinEric Pepin
Create a sandbox, then, instead of doing a validation, actually try to delete the objects. Exceptions will be thrown if they have dependencies and will be successfully deleted if there are none. Then you can run a second piece of code to compare the end result with the state of the org before running the delete. You will then have 2 lists....one of objects that can be deleted, one of objects that can't.
Alain CabonAlain Cabon
Ken, your way of solving this problem is already very effective. The technique with java and the deletion of fields is very close to yours.

The least precise technique is the first one (text search, but the simplest one) and the most accurate could be the third one with the symbol tables but I never use it.

For those who are interested in the techniques with java, you need some jars (zip files of java classes) for starting.

You can find these mandatory jars fully created easily installing the dataloader ( setup > quick find: "dataloader" ) in the default folder: "C:\Program Files (x86)\salesforce.com\Data Loader"
for one jar : dataloader-39.0.0-uber.jar (packages com.sforce.soap.partner  and  com.sforce.ws) and you have the maven repository
for other jars like : force-metadata-api-39.0.0.jar

https://mvnrepository.com/artifact/com.force.api/force-metadata-api/39.0.0

https://mvnrepository.com/artifact/com.force.api/force-wsc

Unfortunately. the wsdl for "tooling" is often (always) unusable (bug) and I use the following workaround.

https://developer.salesforce.com/forums/?id=9060G000000I5A0QAK

That is why it lacks the force-tooling-api.jar in the Maven repository until now?

Regards