330 likes | 650 Views
VSL Deep Dive. Josh Heitzman - Senior Software Design Engineer. VSL is…. Acronym for “Visual Studio Library” Modern C++ library targeting the Visual Studio Platform. Styled after ATL and WTL. Comprised only of header files. No binaries.
E N D
VSL Deep Dive Josh Heitzman - Senior Software Design Engineer
VSL is… • Acronym for “Visual Studio Library” • Modern C++ library targeting the Visual Studio Platform. • Styled after ATL and WTL. • Comprised only of header files. No binaries. • Extensible and customizable (macros can be overriden to change core behavior). • Not a framework like MFC, MPF, .Net Framework, etc.. • Not a complete offering for the entire VS Platform
Resources • <SDK Root>\VisualStudioIntegration\Common\Source\CPP\VSL • VSLArchitecture.htm – class diagrams • Include – VSL header files • MockInterfaces – Windows and Visual Studio Platform Interface mocks • UnitTest\VSLUnitTest.sln – solution with all of the VSL unit tests. • Questions/Issues: • http://forums.microsoft.com/msdn/showforum.aspx?forumid=57&siteid=1 • Prefix post title with “VSL” • Feedback/Suggestions: • http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=123359&SiteID=1 • Blog: • http://blogs.msdn.com/josh_heitzman/
VSL Design Principles • Minimize coupling • Avoid feature creep • Exploit the C++ language and the Microsoft Visual C++ compiler • Facilitate unit testing • Re-use without obstruction • Responsive to requests
Narrowly scoping the functionality of classes: Implement one interface Wrap one VS Service Wrap one related set of Win32 APIs Use of C++ templates to reduce hard dependencies between classes. template< class Derived_T, class VsSiteCache_T = VsSiteCacheLocal> class IVsWindowPaneImpl : public IVsWindowPane template <class Derived_T> class IExtensibleObjectImpl : public IExtensibleObject Minimize coupling
Only the functionality required for the task at hand is implemented. Avoid investing resources in features that may not be needed. class VsOutputWindowUtilities { void OutputMessage( constwchar_t* const szMessage); void OutputMessageWithPreAndPostBarsOfEquals( constwchar_t* const szMessage); }; Avoid feature creep
When possible, fail at compile time rather then runtime Make use of C++ exceptions Use C++ templates and when necessary C pre-processor macros to minimize code redundancy and maximize reuse Use of an extended version of the Resource Allocation Is Initialization paradigm template < class Type_T, size_t NumberOfElements_T> class StaticArray { C_ASSERT( NumberOfElements_T > 0); … __if_exists(Derived_T::GetViewObject) { __if_exists(Derived_T:: GetLocalRegistryCLSIDViewObject) { // Can't speceify both an object and //a clsid C_ASSERT(0); } pViewObject = rDerived.GetViewObject(); } … Exploit the C++ language and the Visual C++ compiler
RAII is used with all resources to ensure their lifetime is properly managed in the face of exceptions. template <...> class Resource { ResourceType m_Resource; Resource(): m_Resource(Values::GetNullValue()) {} Resource(ResourceType resource): m_Resource(resource) {} ~Resource() { Free(); } void Free(); ResourceType Detach(); operator CastType() const; }; Resource Allocation Is Initialization (RAII)
RAII is extended to any set of calls that need balancing. class Suspend { Suspend(This& rThis): m_rThis(rThis) { m_rThis.SendMessage(WM_SETREDRAW, FALSE, 0); m_dwMaskToRestore = static_cast<DWORD>(m_rThis.SendMessage( EM_SETEVENTMASK, 0, ENM_NONE)); } ~SuspendDrawAndNotifications() { m_rThis.SendMessage( EM_SETEVENTMASK, 0, m_dwMaskToRestore); m_rThis.SendMessage(WM_SETREDRAW, TRUE, 0); } This& m_rThis; DWORD m_dwMaskToRestore; }; eXtendened Resource Allocation Is Initialization (XRAII)
Mocks for nearly all VS Platform interfaces Mocks for many Windows Platform interfaces Wrapper classes around some sets of Win32 APIs Mocks for those classes Cursor CursorMock File FileMock Keyboard KeyboardMock Window WindowMock Facilitate unit testing
Re-use without obstruction • Many classes take template parameters • Allows you to provide your own custom implementation for a dependency • Some template defaults will be correct for 99% of cases • A couple of classes using policy based design • a smart pointer and a smart resource • Optional statically bound call backs into a derived class • This is accomplished via __if_exists and __if_notexists • Numerous macros that can be overridden
Responsive to requests • VS SDK release cycle is short • CTP monthly • RTW every 4 months • Designs are never perfect the first time • Even more so when on short cycle • Breaking changes will be made as the demand arises • Short cycle means there won’t be a lot of BCs with any given release
VSL provides help with… • Error and exception handling • Unit testing • Functors and delegates • Comparing various things • Managing resources • The basics necessary to create a VS Package • Command handling • VS Service consumption • Creating a VS Window that hosts a dialog or Win32 control • Creating a VS Document / VS Editor • Automation and VS Macro recording • VS Hierarchies
Error handling macros that convert errors to exceptions Exception handling macros that catch and convert exceptions to HRESULTs VSL_BEGIN_MSG_MAP – message map that catches exceptions Header files: VSLErrorHandlers.h VSLExceptionHandlers.h VSL_STDMETHODTRY{ VSL_CHECKHANDLE_GLE(::GetDC(hWnd)); }VSL_STDMETHODCATCH() return VSL_GET_STDMETHOD_HRESULT(); Error and exception handling
Unit testing framework Mocks for nearly all VS Platform interfaces Mocks for many Windows Platform interfaces Mocks for wrapper classes around some sets of Win32 APIs Including some of ATL::CWindow Header files: VSLUnitTest.h class UnitTest : public UnitTestBase { UnitTest( constchar* const szTestName): UnitTestBase(szTestName) { UTCHK(false); } }; int_cdecl _tmain(int, _TCHAR*) { UTRUN(UnitTest); return VSL::FailureCounter::Get(); } Unit testing
Classes: Functor FunctionPointerFunctor MemberFunctionPointerFunctor Delegate Header Files: VSLCommon.h FunctionPointerFunctor<void ()> functor(&OnEvent1); Delegate<void ()> event1; event1 += functor; event1(); event1 -= functor(); Functors and delegates
Comparing various things • Implemented primarily for the interface mocks • IsStringLessThen can be used with STL algorithms • Header files: • VSLComparison.h
Policy based resource managers: Pointer Resource Header files: VSLCommon.h VSLFont.h typedef Pointer<CoTaskMemPointerTraits> CoTaskMemPointer; CoTaskMemPointer pBuffer = ::CoTaskMemAlloc(iBufferByteSize); CHKPTR(static_cast<LPVOID>(pBuffer), E_OUTOFMEMORY); CHK(0 == ::memcpy_s(pBuffer, iBufferByteSize, GetFileName(), iBufferByteSize), E_FAIL); *ppszFilename = static_cast<LPOLESTR>(pBuffer.Detach()); Managing resources
Classes: IVsPackageImpl IVsInstalledProductImpl Registry map macros Header files: VSLPackage.h class Package : public IVsPackageImpl< Package, &CLSID_Package>, public IVsInstalledProductImpl< IDS_PRODUCT_NAME, IDS_PRODUCT_IDENTIFIER, IDS_PRODUCT_DETAILS, IDI_ LOGO> { VSL_BEGIN_REGISTRY_MAP(IDR_PACKAGE_RGS) ... VSL_END_REGISTRY_MAP() The basics necessary to create a VS Package
VsSiteCache • Can be local or global • IVsPackageImpl uses the global VsSiteCache by default • Once a package is sited anything can then use the global cache by creating an instance of VsSiteCacheGlobal or utilizing the static methods of VsIServiceProviderUtilities directly or via the macros: • VSQS - VsIServiceProviderUtilities<>::QueryService • VSQCS - VsIServiceProviderUtilities<>::QueryCachedService • IVsPaneWindow uses the local VsSiteCache by default • Once window is sited can correctly get context sensitive services like SID_STrackSelection and SID_SVsWindowFrame
Classes: IOleCommandTargetImpl Command map macros VsFontCommandHandling Header files: VSLCommandTarget.h Samples: Menus and Commands Services Tool Window Single View Editor class MenuAndCommandsPackage : ... public IOleCommandTargetImpl<MenuAndCommandsPackage>, ... VSL_BEGIN_COMMAND_MAP() VSL_COMMAND_MAP_ENTRY( GUID_MenuAndCommandsCmdSet, cmdidMyCommand, NULL, &MenuCommandCallback) VSL_COMMAND_MAP_ENTRY_WITH_FLAGS( GUID_MenuAndCommandsCmdSet, cmdidDynVisibility2, NULL, &MenuVisibilityCallback, OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_INVISIBLE) VSL_END_VSCOMMAND_MAP() ... Command handling
Wrapped VS Services: VsOutputWindowUtilities ProfferServiceUtilities OleComponentUIManagerUtilities Can use global or local VsSiteCache. OleComponentUIManagerUtilities<>::ShowMessage( L"Title", L"Message"); VS Service consumption • Header files: • VSLPackage.h • Samples: • Menus and Command • Services • Tool Window • Single View Editor
Classes: IVsWindowPaneImpl Window VsWindowPaneFromResource Header files: VSLWindows.h class Form : public VsWindowPaneFromResource< Form, MAKEINTRESOURCE(IDD_DLG)> Creating a VS Window that hosts a dialog
Classes: IVsWindowPaneImpl Window ListViewWin32Control RichEditWin32Control Win32ControlContainer Header files: VSLControls.h VSLWindows.h class Document : public Win32ControlContainer< RichEditWin32Control<> > class Report : public Win32ControlContainer< ListViewWin32Control< ReportViewTraits< false, false> > > Creating a VS Window that hosts a Win32 control
Classes VsWindowFrameEventSink ISelectionContainerImpl ISelectionContainerSingleItemImpl Header files VSLWindows.h class WindowPane : public IVsWindowPaneImpl<WindowPane>, public VsWindowFrameEventSink<WindowPane>, public ISomeInterface, public ISelectionContainerSingleItemImpl< WindowPane, ISomeInterface> Fully integrating a VS Window
Creating a VS Document / VS Editor • Classes: • IVsEditorFactoryImpl • IVsFindTargetImpl • SingleViewFindInFilesOutputWindowIntegrationImpl • File • DocumentPersistanceBase • Header Files: • VSLFile.h • VSLFindAndReplace.h • VSLWindow.h • Samples: • Single View Editor
Classes: IExtensibleObjectImpl VsMacroRecorder Header Files: VSLAutomation.h Samples: Single View Editor void RecordCommand( wchar_t* szCommand) { if(m_Recorder.IsRecording( GetVsSiteCache())) { CStringW strLine = L"ActiveDocument.Object."; strLine += szCommand; m_Recorder.RecordLine( strLine); } } Automation and VS Macro recording
Classes: IVsHierarchyImpl IVsUIHierarchyImpl IVsHierarchyEventsDelegate VsHierarchyRootItemBase VsHierarchyItemBase VsUIHierarchyItemBase VsHierarchyRootItemBase HierarchyNode C++ Interfaces: IVsHierarchyItem IVsUIHierarchyItem IVsHierarchyRootItem IVsUIHierarchyRootItem Header Files: VSLHierarchy.h VSLHierarchyNode.h Samples: Extensiblity Explorer
Miscellaneous Win32 Resource Managers/Wrappers • Classes: • Library – HMODULE’s from ::LoadLibrary • DeviceContext – HDC’s from ::GetDC • Cursor – HCURSOR from ::LoadCursor • Keyboard • These classes only provide what was necessary for the reference samples, but can be easily expanded as needed. For example: • Library has no methods (just constructor/destructor) • DeviceContext only has EnumFontFamiliesExW • Cursor only has Activate • Keyboard only has IsKeyDown
Data Collection • Do you: • Have existing packages written in C++? • Use VSL in C++ packages? • Plan to use VSL in C++ packages in the future? • Unit test existing C++ packages? • Use VSL for unit testing C++ packages? • Plan to use VSL for unit testing C++ packages in the future? • Plan to write new packages in C++ in the future? • What kind of package (project system, editor, designer, etc.)? • Plan to expand add additional features in C++? • What type of features? • Want better tools for creating scenario tests? • Want sample scenario tests?
Data Collection continued • Plan to migrate existing C++ package to managed? • C++/CLI? • C#? • Other? • Over what time frame?