That's a royal PITA because of the port bit definitions. Instead, its better to #define pins named by function and localize the brain damage by avoiding all use of PORTA vs GPIO and TRISA vs TRISIO except in your hardware.h
Yeah, Ian. I do that, too. But sometimes ports and registers are important to the software for byte instructions/manipulations to save instruction cycles and/or where state changes must happen at the same time, rather than serially.
You can do those things through this additional layer, as well, but then you need more defines (and more cumbersome code, which is the cost for pin flexibility).
PORTA vs GPIO at least keeps things the same across devices.
#define HB_LED LATBbits.LATB6 // Used for heartbeat
#define ADC1 LATDbits.LATD5
In order to do more involved/minute/direct stuffs, you might end up needing more defines ala:
#define HB_LED.port PORTA
#define HB_LED.tris TRISA
#define HB_LED.lat LATA
#define HB_LED.pin 4
#define HB_LED PORTA,4
Even in your defines, you don't have to write/think GPIO/TRISIO, anymore, once you have defined it to PORTA/TRISA.