Visual Studio Tools Platform RTB

Download Report

Transcript Visual Studio Tools Platform RTB

VSL Deep Dive
Josh Heitzman - Senior Software Design Engineer
1
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
2
VSL Effect
Code
Lines
Comment
Lines
Characters
Semicolons
Functions
C++ Tool Window
828
508
53,858
228
34
C# Tool Window
844
724
63,686
433
49
C++ Menus & Commands
178
222
18,996
38
11
C# Menus & Commands
227
201
20,498
90
10
C++ Services
315
320
28,230
78
15
C# Services
270
289
26,773
101
13
C++ Single View Editor
2,653
1,203
130,689
879
142
C# Single View Editor
3,253
1,620
251,990
1,147
276
C++ Package
81
201
13,648
7
3
C# Package
204
261
22,284
72
17
Feature equivalent
Not feature equivalent
3
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/
4
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
5
Minimize coupling
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.
6
template<
class Derived_T,
class VsSiteCache_T =
VsSiteCacheLocal>
class IVsWindowPaneImpl :
public IVsWindowPane
template <class Derived_T>
class IExtensibleObjectImpl :
public IExtensibleObject
Avoid feature creep
Only the
functionality
required for the
task at hand is
implemented.
Avoid investing
resources in
features that
may not be
needed.
7
class VsOutputWindowUtilities
{
void
OutputMessage(
const wchar_t* const szMessage);
void
OutputMessageWithPreAndPostBarsOfEquals(
const wchar_t* const szMessage);
};
Exploit the C++ language and the Visual C++ compiler
•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
8
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();
}
…
Resource Allocation Is Initialization (RAII)
RAII is used with all
resources to ensure
their lifetime is
properly managed in
the face of
exceptions.
9
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;
};
eXtendened Resource Allocation Is Initialization (XRAII)
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;
};
10
Facilitate unit testing
•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
11
Cursor
CursorMock
File
FileMock
Keyboard
KeyboardMock
Window
WindowMock
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
12
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
13
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
14
Error and exception handling
Error handling macros
that convert errors to
exceptions
VSL_STDMETHODTRY{
Exception handling
macros that catch and
convert exceptions to
HRESULTs
}VSL_STDMETHODCATCH()
VSL_BEGIN_MSG_MAP –
message map that
catches exceptions
Header files:
•VSLErrorHandlers.h
•VSLExceptionHandlers.h
15
VSL_CHECKHANDLE_GLE(::GetDC(hWnd));
return VSL_GET_STDMETHOD_HRESULT();
Unit testing
•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
16
class UnitTest :
public UnitTestBase
{
UnitTest(
const char* const szTestName):
UnitTestBase(szTestName)
{
UTCHK(false);
}
};
int _cdecl _tmain(int, _TCHAR*)
{
UTRUN(UnitTest);
return VSL::FailureCounter::Get();
}
Functors and delegates
Classes:
•Functor
•FunctionPointerFunctor
•MemberFunctionPointerFunctor
•Delegate
Header Files:
•VSLCommon.h
17
FunctionPointerFunctor<void ()>
functor(&OnEvent1);
Delegate<void ()> event1;
event1 += functor;
event1();
event1 -= functor();
Comparing various things
•Implemented primarily for the interface mocks
•IsStringLessThen can be used with STL algorithms
•Header files:
•VSLComparison.h
18
Managing resources
typedef Pointer<CoTaskMemPointerTraits>
Policy based
resource managers: CoTaskMemPointer;
•Pointer
•Resource
Header files:
•VSLCommon.h
•VSLFont.h
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());
19
The basics necessary to create a VS Package
Classes:
•IVsPackageImpl
•IVsInstalledProductImpl
Registry map macros
Header files:
•VSLPackage.h
20
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()
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
21
Command handling
Classes:
•IOleCommandTargetImpl
•Command map macros
•VsFontCommandHandling
Header files:
•VSLCommandTarget.h
Samples:
•Menus and Commands
•Services
•Tool Window
•Single View Editor
22
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()
...
VS Service consumption
Wrapped VS Services:
•VsOutputWindowUtilities
•ProfferServiceUtilities
•OleComponentUIManagerUtilities
Can use global or local VsSiteCache.
Header files:
•VSLPackage.h
Samples:
•Menus and Command
•Services
•Tool Window
•Single View Editor
OleComponentUIManagerUtilities<>::ShowMessage(
L"Title",
L"Message");
23
Creating a VS Window that hosts a dialog
Classes:
•IVsWindowPaneImpl
•Window
•VsWindowPaneFromResource
Header files:
•VSLWindows.h
24
class Form :
public
VsWindowPaneFromResource<
Form,
MAKEINTRESOURCE(IDD_DLG)>
Creating a VS Window that hosts a Win32 control
Classes:
•IVsWindowPaneImpl
•Window
•ListViewWin32Control
•RichEditWin32Control
•Win32ControlContainer
Header files:
•VSLControls.h
•VSLWindows.h
25
class Document :
public
Win32ControlContainer<
RichEditWin32Control<> >
class Report :
public
Win32ControlContainer<
ListViewWin32Control<
ReportViewTraits<
false,
false> > >
Fully integrating a VS Window
Classes
•VsWindowFrameEventSink
•ISelectionContainerImpl
•ISelectionContainerSingleItemImpl
Header files
•VSLWindows.h
26
class WindowPane :
public IVsWindowPaneImpl<WindowPane>,
public
VsWindowFrameEventSink<WindowPane>,
public ISomeInterface,
public
ISelectionContainerSingleItemImpl<
WindowPane,
ISomeInterface>
Creating a VS Document / VS Editor
Classes:
•IVsEditorFactoryImpl
•IVsFindTargetImpl
•SingleViewFindInFilesOutputWindowIntegrationImpl
•File
•DocumentPersistanceBase
Header Files:
•VSLFile.h
•VSLFindAndReplace.h
•VSLWindow.h
Samples:
•Single View Editor
27
Automation and VS Macro recording
Classes:
•IExtensibleObjectImpl
•VsMacroRecorder
Header Files:
•VSLAutomation.h
Samples:
•Single View Editor
28
void RecordCommand(
wchar_t* szCommand)
{
if(m_Recorder.IsRecording(
GetVsSiteCache()))
{
CStringW strLine =
L"ActiveDocument.Object.";
strLine += szCommand;
m_Recorder.RecordLine(
strLine);
}
}
Classes:
•IVsHierarchyImpl
•IVsUIHierarchyImpl
•IVsHierarchyEventsDelegate
•VsHierarchyRootItemBase
•VsHierarchyItemBase
•VsUIHierarchyItemBase
•VsHierarchyRootItemBase
•HierarchyNode
C++ Interfaces:
•IVsHierarchyItem
•IVsUIHierarchyItem
•IVsHierarchyRootItem
•IVsUIHierarchyRootItem
Header Files:
•VSLHierarchy.h
•VSLHierarchyNode.h
Samples:
•Extensiblity Explorer
29
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
30
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?
31
Data Collection continued
•Plan to migrate existing C++ package to managed?
•C++/CLI?
•C#?
•Other?
•Over what time frame?
32