Whole Tomato Software Forums
Whole Tomato Software Forums
Main Site | Profile | Register | Active Topics | Members | Search | FAQ
 All Forums
 Visual Assist
 Feature Requests
 Exclusion list for . -> expansion / correction

You must be registered to post a reply.
Click here to register.

Screensize:
UserName:
Password:
Format: BoldItalicizeUnderlineStrikethrough Align leftCenterAlign right Insert horizontal ruleUpload and insert imageInsert hyperlinkInsert email addressInsert codeInsert quoted textInsert listInsert Emoji
   
Message:

Forum code is on.
Html is off.

 
Check to subscribe to this topic.
   

T O P I C    R E V I E W
Mordachai Posted - Oct 15 2012 : 2:29:26 PM
I sometimes write wrappers for pointer-types. e.g. FILE*. or HANDLE types, which are ostensibly defined as pointers, but aren't really pointers (and with FILE*, it's not intended to be dereferenced by the programmer).

So... if I could have an exclusionary list for VAX to say "these are not really pointers, PLEASE do NOT replace . operator with -> operator".

I have to hit BS a hundred times a day, and if I forget immediately, then I have to BS twice, type . again, and again remember to hit BS to undo the !@#$!@#$ replacement AGAIN.

(Sigh... frustrating after a few hours) [!]

As always, VAX is an awesome product - love using it overall.
5   L A T E S T    R E P L I E S    (Newest First)
Mordachai Posted - Oct 17 2012 : 08:46:42 AM
Wow - that looks like a solution to me. :)

I'll give it a shot & report back.
feline Posted - Oct 16 2012 : 3:29:28 PM
Thank you for the clear sample code. Assuming you are able to edit the FilePointer class, I think I have a solution for you, this is working here.

Instead of trying to add an exclusion list, it is possible to hide the operator->() member function from VA.

In the FilePointer class I have replaced the operator->() function with the slightly messy code:

//	FILE* operator -> () { return *m_pFileWrapper; }		// allow the C run-time library macros to work
	// work around to hide operator function from Visual Assist X
#define VA_INVISIBLE_OPERATOR_OVERLOAD FILE* operator -> () { return *m_pFileWrapper; }
	VA_INVISIBLE_OPERATOR_OVERLOAD

which will compile to the same thing.

Next create a new file called "va_stdafx.h", place it into the same directory as your .SLN or .VCPROJ file, and add the single line:

#define VA_INVISIBLE_OPERATOR_OVERLOAD

make sure this "va_stdafx.h" file ends with a blank line. Do Not add this file to your solution.

Now press the button:

VA Options -> Performance -> Rebuild symbol databases

and restart your IDE. The va_stdafx.h file is explained here:

http://docs.wholetomato.com?W302

basically I am hiding this macro from our parser, so hiding this member function from our parser, while keeping it in your code. What happens when you try this?
Mordachai Posted - Oct 16 2012 : 09:52:50 AM
Please note that for other smart pointer esq classes I would want the auto-correction. So I don't think that VAX can be smart enough to know which I mean, without help.

The help I'm suggesting is a simple "exclusion" list or some such. Of course, simple is in the eye of the beholder! ;)
Mordachai Posted - Oct 16 2012 : 08:14:43 AM
FilePointer holds a FileWrapper, which is a wrapper/shim for a FILE* which implements some RAII policy (currently either close or flush on destruction). FilePointer is used to hide the policy, and give an opaque interface for all consumers of a file stream.

The main thing seems to be that I've defined an operator->() (necessary because of how the C run-time library is written).

	class FilePointer
	{
		FilePointer() : m_pFileWrapper(nullptr) { }
		FilePointer(FileWrapper * pfw) : m_pFileWrapper(pfw) { }
		FilePointer(const FilePointer & rhs) : m_pFileWrapper(rhs.m_pFileWrapper), m_references(rhs.m_references) { }

		// accessors
		operator FILE* () { return *m_pFileWrapper; }			// allow rewind(fp), etc. !WARNING! This is the operator that allows for much mischief!
		FILE* operator -> () { return *m_pFileWrapper; }		// allow the C run-time library macros to work
		FILE* get() const { return *m_pFileWrapper; }			// explicit access

		// comparisons
		bool operator == (const FilePointer & rhs) const { return m_pFileWrapper == rhs.m_pFileWrapper; }
		bool operator == (FILE* fp) const { return fp == *m_pFileWrapper; }
		bool operator != (const FilePointer & rhs) const { return m_pFileWrapper != rhs.m_pFileWrapper; }
		bool operator != (FILE* fp) const { return fp != *m_pFileWrapper; }

		//////////////////////////////////////////////////////////////////////////
		// Binary object I/O

		// reads a single item of type T from our stream
		template <typename T>
		void read(T & thing)
		{
			// don't allow us to generate a 'read pointer' function!
			BOOST_STATIC_ASSERT(!(boost::is_pointer<T>::value));

			if (!fread(get(), thing))
				throw IOError(__FUNCTION__);
		}

		// reads in a single item of type T from our stream as a return value (e.g. char c = read<char>())
		template <typename T> T read() { T thing; read(thing); return thing; }

		// write object
		template <typename T>
		void write(T const & thing)
		{
			// don't allow us to generate a 'write out a pointer' function!
			BOOST_STATIC_ASSERT(!(boost::is_pointer<T>::value));

			// write out the binary of thing
			if (!fwrite(get(), thing))
				throw IOError(__FUNCTION__);
		}
	protected:

		FileWrapper *	m_pFileWrapper;	// pointer to FILE* wrapper
		ReferenceCount	m_references;	// reference count
	};

	class FileWrapper
	{
	public:
		// access the raw FILE*
		FILE* get() const { return this ? m_fp : nullptr; }
		operator FILE* () { return this ? m_fp : nullptr; }

		// relinquish ownership of our FILE*
		FILE* release()
		{
			TRACE_FILE_WRAPPER("%s[%p] releasing %X\\n", typeid(*this).name(), this, m_fp);
			FILE* fp = m_fp;
			m_fp = NULL;
			return fp;
		}

		// explicitly close the file
		virtual int close()
		{
			// fclose() docs indicate that closing a NULL stream
			// results in the invalid parameter handler being called
			// so we simply indicate success if no file handle is assigned to us
			if (!m_fp)
				return 0;	

			// execute the actual close
			const int error = ::fclose(m_fp);
			TRACE_FILE_WRAPPER("%s[%p] closed %X (status = %d)\\n", typeid(*this).name(), this, m_fp, error);

			// nullify ourself only if we succeeded in closing the file stream
			if (!error)
				m_fp = NULL;

			return error;
		}

		// destructor (polymorphic to allow subclasses to terminate properly)
		virtual ~FileWrapper() 
		{
			TRACE_FILE_WRAPPER("%s[%p] deleted\\n", typeid(*this).name(), this);
		}

	protected:
		// force only subclasses to really be used by hiding the ctor

		// constructor
		FileWrapper(FILE* fp) : m_fp(fp)
		{
			TRACE_FILE_WRAPPER("%s[%p] created %X\\n", typeid(*this).name(), this, m_fp);
		}

		// disallow copy ctor and assignment
		FileWrapper(const FileWrapper &);
		FileWrapper & operator = (const FileWrapper &);

		// the underlying file
		FILE*	m_fp;
	};


Is this enough information?

I am only realizing that the dereference "correction" only occurs because I have included an operator->(), and NOT because it is a type of FILE*, which I had forgotten (this class has evolved over the years).

So, I guess my suggestion is: Can I tell VAX to NOT assume I mean -> when I type . for this and other classes like it?
accord Posted - Oct 15 2012 : 10:19:18 PM
Can you please post an example code snippet about how you ostensibly define as pointers, and a usage of this object in her guise? You know where the not welcomed correction happens.
So I can see clearly what is happening. Thanks.

© 2023 Whole Tomato Software, LLC Go To Top Of Page
Snitz Forums 2000